summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib')
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp680
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp852
-rw-r--r--contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXABI.h16
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp138
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp295
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp216
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp253
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp131
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp243
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp63
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/AST/InheritViz.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp779
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp534
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NSAPI.cpp103
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ParentMap.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp223
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp331
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp1225
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp143
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp223
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h53
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp301
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp129
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp1121
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp209
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp963
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp132
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp1380
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp218
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h17
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp387
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.h18
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp546
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h13
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp1364
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h598
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp75
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp1121
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp180
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp103
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp75
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp188
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp333
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp178
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp2584
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h461
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp180
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp2280
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp118
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGValue.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp176
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h541
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp420
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h59
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp913
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h135
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h29
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp1271
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h148
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp472
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp1770
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp193
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h4
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp1038
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Action.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp979
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/MinGWToolChain.cpp175
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Multilib.cpp125
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp677
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp1968
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.h349
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp4026
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.h531
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp244
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h87
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Format.cpp465
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.h320
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp643
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h40
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp952
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h133
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp443
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp112
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp316
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp402
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp450
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp188
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp96
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp114
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp117
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/Intrin.h364
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__stddef_max_align_t.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h15
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/adxintrin.h17
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/altivec.h13849
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ammintrin.h155
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/arm_acle.h76
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx2intrin.h324
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h1200
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h131
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h242
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h325
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h1963
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h1840
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h353
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h1915
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avxintrin.h493
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h21
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/bmiintrin.h35
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cuda_builtin_vars.h110
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/emmintrin.h521
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/f16cintrin.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fma4intrin.h69
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fmaintrin.h69
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h55
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/htmintrin.h226
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h363
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/immintrin.h27
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/inttypes.h102
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h15
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mm3dnow.h57
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mmintrin.h138
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/module.modulemap17
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pmmintrin.h29
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/popcntintrin.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/rtmintrin.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/s390intrin.h35
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/shaintrin.h17
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/smmintrin.h79
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdatomic.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tbmintrin.h50
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tmmintrin.h65
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/unwind.h18
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xmmintrin.h257
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xopintrin.h229
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xtestintrin.h41
-rw-r--r--contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp273
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp348
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp154
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp319
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp122
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp437
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp553
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp169
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp819
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp130
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp129
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h22
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp128
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Scope.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp139
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp1214
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp642
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp1255
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp513
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp529
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp1302
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp993
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp638
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp106
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp548
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp832
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp268
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp382
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp165
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp2011
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp378
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp656
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp212
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp370
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp320
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp143
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp1606
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h469
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h24
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp1524
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp1119
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp156
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp1504
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp307
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/Module.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp552
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp475
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp97
430 files changed, 68755 insertions, 31489 deletions
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
index dddc886..f33ad21 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
@@ -124,7 +124,7 @@ public:
}
}
- virtual ~CaptureDiagnosticConsumer() {
+ ~CaptureDiagnosticConsumer() override {
assert(!HasBegunSourceFile && "FinishCapture not called!");
}
@@ -166,7 +166,8 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
}
static CompilerInvocation *
-createInvocationForMigration(CompilerInvocation &origCI) {
+createInvocationForMigration(CompilerInvocation &origCI,
+ const PCHContainerOperations &PCHContainerOps) {
std::unique_ptr<CompilerInvocation> CInvok;
CInvok.reset(new CompilerInvocation(origCI));
PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
@@ -178,9 +179,8 @@ createInvocationForMigration(CompilerInvocation &origCI) {
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
new IgnoringDiagConsumer()));
- std::string OriginalFile =
- ASTReader::getOriginalSourceFile(PPOpts.ImplicitPCHInclude,
- FileMgr, *Diags);
+ std::string OriginalFile = ASTReader::getOriginalSourceFile(
+ PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerOps, *Diags);
if (!OriginalFile.empty())
PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
PPOpts.ImplicitPCHInclude.clear();
@@ -230,11 +230,11 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
// checkForManualIssues.
//===----------------------------------------------------------------------===//
-bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
- const FrontendInputFile &Input,
- DiagnosticConsumer *DiagClient,
- bool emitPremigrationARCErrors,
- StringRef plistOut) {
+bool arcmt::checkForManualIssues(
+ CompilerInvocation &origCI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
+ StringRef plistOut) {
if (!origCI.getLangOpts()->ObjC1)
return false;
@@ -247,7 +247,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
assert(!transforms.empty());
std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(createInvocationForMigration(origCI));
+ CInvok.reset(createInvocationForMigration(origCI, *PCHContainerOps));
CInvok->getFrontendOpts().Inputs.clear();
CInvok->getFrontendOpts().Inputs.push_back(Input);
@@ -263,8 +263,8 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
- std::unique_ptr<ASTUnit> Unit(
- ASTUnit::LoadFromCompilerInvocationAction(CInvok.release(), Diags));
+ std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
+ CInvok.release(), PCHContainerOps, Diags));
if (!Unit) {
errRec.FinishCapture();
return true;
@@ -330,12 +330,11 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
// applyTransformations.
//===----------------------------------------------------------------------===//
-static bool applyTransforms(CompilerInvocation &origCI,
- const FrontendInputFile &Input,
- DiagnosticConsumer *DiagClient,
- StringRef outputDir,
- bool emitPremigrationARCErrors,
- StringRef plistOut) {
+static bool
+applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient, StringRef outputDir,
+ bool emitPremigrationARCErrors, StringRef plistOut) {
if (!origCI.getLangOpts()->ObjC1)
return false;
@@ -343,15 +342,16 @@ static bool applyTransforms(CompilerInvocation &origCI,
// Make sure checking is successful first.
CompilerInvocation CInvokForCheck(origCI);
- if (arcmt::checkForManualIssues(CInvokForCheck, Input, DiagClient,
- emitPremigrationARCErrors, plistOut))
+ if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
+ DiagClient, emitPremigrationARCErrors,
+ plistOut))
return true;
CompilerInvocation CInvok(origCI);
CInvok.getFrontendOpts().Inputs.clear();
CInvok.getFrontendOpts().Inputs.push_back(Input);
-
- MigrationProcess migration(CInvok, DiagClient, outputDir);
+
+ MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
@@ -376,22 +376,22 @@ static bool applyTransforms(CompilerInvocation &origCI,
}
}
-bool arcmt::applyTransformations(CompilerInvocation &origCI,
- const FrontendInputFile &Input,
- DiagnosticConsumer *DiagClient) {
- return applyTransforms(origCI, Input, DiagClient,
+bool arcmt::applyTransformations(
+ CompilerInvocation &origCI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient) {
+ return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
StringRef(), false, StringRef());
}
-bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
- const FrontendInputFile &Input,
- DiagnosticConsumer *DiagClient,
- StringRef outputDir,
- bool emitPremigrationARCErrors,
- StringRef plistOut) {
+bool arcmt::migrateWithTemporaryFiles(
+ CompilerInvocation &origCI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient, StringRef outputDir,
+ bool emitPremigrationARCErrors, StringRef plistOut) {
assert(!outputDir.empty() && "Expected output directory path");
- return applyTransforms(origCI, Input, DiagClient,
- outputDir, emitPremigrationARCErrors, plistOut);
+ return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
+ emitPremigrationARCErrors, plistOut);
}
bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
@@ -432,7 +432,7 @@ public:
ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
: ARCMTMacroLocs(ARCMTMacroLocs) { }
- void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override {
if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
@@ -465,7 +465,7 @@ public:
if (Listener)
Listener->start(ctx);
}
- ~RewritesApplicator() {
+ ~RewritesApplicator() override {
if (Listener)
Listener->finish();
}
@@ -499,10 +499,12 @@ public:
/// \brief Anchor for VTable.
MigrationProcess::RewriteListener::~RewriteListener() { }
-MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
- DiagnosticConsumer *diagClient,
- StringRef outputDir)
- : OrigCI(CI), DiagClient(diagClient), HadARCErrors(false) {
+MigrationProcess::MigrationProcess(
+ const CompilerInvocation &CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *diagClient, StringRef outputDir)
+ : OrigCI(CI), PCHContainerOps(PCHContainerOps), DiagClient(diagClient),
+ HadARCErrors(false) {
if (!outputDir.empty()) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
@@ -515,7 +517,7 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
bool MigrationProcess::applyTransform(TransformFn trans,
RewriteListener *listener) {
std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(createInvocationForMigration(OrigCI));
+ CInvok.reset(createInvocationForMigration(OrigCI, *PCHContainerOps));
CInvok->getDiagnosticOpts().IgnoreWarnings = true;
Remapper.applyMappings(CInvok->getPreprocessorOpts());
@@ -537,7 +539,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- CInvok.release(), Diags, ASTAction.get()));
+ CInvok.release(), PCHContainerOps, Diags, ASTAction.get()));
if (!Unit) {
errRec.FinishCapture();
return true;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
index 0ed36dd..39a922f 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
@@ -16,6 +16,7 @@ using namespace arcmt;
bool CheckAction::BeginInvocation(CompilerInstance &CI) {
if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(),
+ CI.getPCHContainerOperations(),
CI.getDiagnostics().getClient()))
return false; // errors, stop the action.
@@ -29,6 +30,7 @@ CheckAction::CheckAction(FrontendAction *WrappedAction)
bool ModifyAction::BeginInvocation(CompilerInstance &CI) {
return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(),
+ CI.getPCHContainerOperations(),
CI.getDiagnostics().getClient());
}
@@ -36,12 +38,10 @@ ModifyAction::ModifyAction(FrontendAction *WrappedAction)
: WrapperFrontendAction(WrappedAction) {}
bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
- if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
- getCurrentInput(),
- CI.getDiagnostics().getClient(),
- MigrateDir,
- EmitPremigrationARCErros,
- PlistOut))
+ if (arcmt::migrateWithTemporaryFiles(
+ CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(),
+ CI.getDiagnostics().getClient(), MigrateDir, EmitPremigrationARCErros,
+ PlistOut))
return false; // errors, stop the action.
// We only want to see diagnostics emitted by migrateWithTemporaryFiles.
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
index 52c424c..b61a421 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -48,7 +48,7 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
};
void migrateDecl(Decl *D);
- void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D);
+ void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
void migrateProtocolConformance(ASTContext &Ctx,
const ObjCImplementationDecl *ImpDecl);
void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
@@ -245,17 +245,16 @@ namespace {
(Msg->getReceiverKind() != ObjCMessageExpr::Instance &&
Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance))
return false;
+ if (const Expr *Receiver = Msg->getInstanceReceiver())
+ if (Receiver->getType()->isObjCBuiltinType())
+ return false;
+
const ObjCMethodDecl *Method = Msg->getMethodDecl();
if (!Method)
return false;
if (!Method->isPropertyAccessor())
return false;
- const ObjCInterfaceDecl *IFace =
- NS.getASTContext().getObjContainingInterface(Method);
- if (!IFace)
- return false;
-
const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
if (!Prop)
return false;
@@ -305,6 +304,10 @@ namespace {
BegLoc = PP.getLocForEndOfToken(BegLoc);
SourceLocation EndLoc = RHS->getLocStart();
EndLoc = EndLoc.getLocWithOffset(-1);
+ const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
+ // Add a space after '=' if there is no space between RHS and '='
+ if (colon && colon[0] == ':')
+ PropertyDotString += " ";
SourceRange Range(BegLoc, EndLoc);
commit.replace(Range, PropertyDotString);
// remove '[' ']'
@@ -352,8 +355,8 @@ public:
bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
// Do depth first; we want to rewrite the subexpressions first so that if
// we have to move expressions we will move them already rewritten.
- for (Stmt::child_range range = E->children(); range; ++range)
- if (!TraverseStmt(*range))
+ for (Stmt *SubStmt : E->children())
+ if (!TraverseStmt(SubStmt))
return false;
return WalkUpFromObjCMessageExpr(E);
@@ -465,7 +468,7 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
ASTContext &Context = NS.getASTContext();
bool LParenAdded = false;
std::string PropertyString = "@property ";
- if (UseNsIosOnlyMacro && Context.Idents.get("NS_NONATOMIC_IOSONLY").hasMacroDefinition()) {
+ if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {
PropertyString += "(NS_NONATOMIC_IOSONLY";
LParenAdded = true;
} else if (!Atomic) {
@@ -575,7 +578,7 @@ static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) {
return false;
}
-void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
+void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
ObjCContainerDecl *D) {
if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
return;
@@ -616,7 +619,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
continue;
HasAtleastOneRequiredProperty = true;
- DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
+ DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
if (R.size() == 0) {
// Relax the rule and look into class's implementation for a synthesize
// or dynamic declaration. Class is implementing a property coming from
@@ -647,7 +650,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
continue;
if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
continue;
- DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
+ DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
if (R.size() == 0)
return false;
bool match = false;
@@ -768,19 +771,34 @@ static void rewriteToNSMacroDecl(ASTContext &Ctx,
const TypedefDecl *TypedefDcl,
const NSAPI &NS, edit::Commit &commit,
bool IsNSIntegerType) {
- QualType EnumUnderlyingT = EnumDcl->getPromotionType();
- assert(!EnumUnderlyingT.isNull()
+ QualType DesignatedEnumType = EnumDcl->getIntegerType();
+ assert(!DesignatedEnumType.isNull()
&& "rewriteToNSMacroDecl - underlying enum type is null");
PrintingPolicy Policy(Ctx.getPrintingPolicy());
- std::string TypeString = EnumUnderlyingT.getAsString(Policy);
+ std::string TypeString = DesignatedEnumType.getAsString(Policy);
std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
ClassString += TypeString;
ClassString += ", ";
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
- SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
+ SourceLocation EndLoc;
+ if (EnumDcl->getIntegerTypeSourceInfo()) {
+ TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo();
+ TypeLoc TLoc = TSourceInfo->getTypeLoc();
+ EndLoc = TLoc.getLocEnd();
+ const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc);
+ unsigned count = 0;
+ if (lbrace)
+ while (lbrace[count] != '{')
+ ++count;
+ if (count > 0)
+ EndLoc = EndLoc.getLocWithOffset(count-1);
+ }
+ else
+ EndLoc = EnumDcl->getLocStart();
+ SourceRange R(EnumDcl->getLocStart(), EndLoc);
commit.replace(R, ClassString);
// This is to remove spaces between '}' and typedef name.
SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
@@ -902,7 +920,7 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl) {
if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
- EnumDcl->isDeprecated() || EnumDcl->getIntegerTypeSourceInfo())
+ EnumDcl->isDeprecated())
return false;
if (!TypedefDcl) {
if (NSIntegerTypedefed) {
@@ -1259,7 +1277,7 @@ void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
QualType RT = OM->getReturnType();
if (!TypeIsInnerPointer(RT) ||
- !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
+ !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
return;
edit::Commit commit(*Editor);
@@ -1270,9 +1288,9 @@ void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
ObjCPropertyDecl *P) {
QualType T = P->getType();
-
+
if (!TypeIsInnerPointer(T) ||
- !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
+ !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
return;
edit::Commit commit(*Editor);
commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER ");
@@ -1390,7 +1408,7 @@ static bool AuditedType (QualType AT) {
void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
if (CFFunctionIBCandidates.empty())
return;
- if (!Ctx.Idents.get("CF_IMPLICIT_BRIDGING_ENABLED").hasMacroDefinition()) {
+ if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {
CFFunctionIBCandidates.clear();
FileId = FileID();
return;
@@ -1465,16 +1483,14 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
RetEffect Ret = CE.getReturnValue();
const char *AnnotationString = nullptr;
if (Ret.getObjKind() == RetEffect::CF) {
- if (Ret.isOwned() &&
- Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
+ if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
AnnotationString = " CF_RETURNS_RETAINED";
else if (Ret.notOwned() &&
- Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
+ NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
AnnotationString = " CF_RETURNS_NOT_RETAINED";
}
else if (Ret.getObjKind() == RetEffect::ObjC) {
- if (Ret.isOwned() &&
- Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
+ if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
AnnotationString = " NS_RETURNS_RETAINED";
}
@@ -1491,13 +1507,13 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
- Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
+ NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
Editor->commit(commit);
}
else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
- Ctx.Idents.get("NS_CONSUMED").hasMacroDefinition()) {
+ NSAPIObj->isMacroDefined("NS_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
Editor->commit(commit);
@@ -1582,11 +1598,10 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
RetEffect Ret = CE.getReturnValue();
const char *AnnotationString = nullptr;
if (Ret.getObjKind() == RetEffect::CF) {
- if (Ret.isOwned() &&
- Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
+ if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
AnnotationString = " CF_RETURNS_RETAINED";
else if (Ret.notOwned() &&
- Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
+ NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
AnnotationString = " CF_RETURNS_NOT_RETAINED";
}
else if (Ret.getObjKind() == RetEffect::ObjC) {
@@ -1600,8 +1615,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
break;
default:
- if (Ret.isOwned() &&
- Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
+ if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
AnnotationString = " NS_RETURNS_RETAINED";
break;
}
@@ -1620,7 +1634,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
- Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
+ NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
Editor->commit(commit);
@@ -1640,12 +1654,12 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
- if (CE.getReceiver() == DecRefMsg &&
+
+ if (CE.getReceiver() == DecRefMsg &&
!MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
MethodDecl->getMethodFamily() != OMF_init &&
MethodDecl->getMethodFamily() != OMF_release &&
- Ctx.Idents.get("NS_CONSUMES_SELF").hasMacroDefinition()) {
+ NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
edit::Commit commit(*Editor);
commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
Editor->commit(commit);
@@ -1711,7 +1725,7 @@ void ObjCMigrateASTConsumer::inferDesignatedInitializers(
const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
if (!IFace || IFace->hasDesignatedInitializers())
return;
- if (!Ctx.Idents.get("NS_DESIGNATED_INITIALIZER").hasMacroDefinition())
+ if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
return;
for (const auto *MD : ImplD->instance_methods()) {
@@ -1772,9 +1786,7 @@ public:
: SourceMgr(SM), OS(OS) {
OS << "[\n";
}
- ~JSONEditWriter() {
- OS << "]\n";
- }
+ ~JSONEditWriter() override { OS << "]\n"; }
private:
struct EntryWriter {
@@ -1858,13 +1870,16 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
if (canModify(CDecl))
- migrateObjCInterfaceDecl(Ctx, CDecl);
+ migrateObjCContainerDecl(Ctx, CDecl);
if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
if (canModify(CatDecl))
- migrateObjCInterfaceDecl(Ctx, CatDecl);
+ migrateObjCContainerDecl(Ctx, CatDecl);
}
- else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
+ else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
+ if (canModify(PDecl))
+ migrateObjCContainerDecl(Ctx, PDecl);
+ }
else if (const ObjCImplementationDecl *ImpDecl =
dyn_cast<ObjCImplementationDecl>(*D)) {
if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
@@ -2268,7 +2283,7 @@ bool arcmt::getFileRemappingsFromFileList(
continue;
}
- remap.push_back(std::make_pair(I->first->getName(), TempFile));
+ remap.emplace_back(I->first->getName(), TempFile);
}
return hasErrorOccurred;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
index 53398b2..9a51690 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
@@ -100,16 +100,18 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath,
// Output the location of the bug.
o << " <key>location</key>\n";
- EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2);
+ EmitLocation(o, SM, D.getLocation(), FM, 2);
// Output the ranges (if any).
- StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end();
-
- if (RI != RE) {
+ if (!D.getRanges().empty()) {
o << " <key>ranges</key>\n";
o << " <array>\n";
- for (; RI != RE; ++RI)
- EmitRange(o, SM, LangOpts, *RI, FM, 4);
+ for (auto &R : D.getRanges()) {
+ CharSourceRange ExpansionRange(SM.getExpansionRange(R.getAsRange()),
+ R.isTokenRange());
+ EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),
+ FM, 4);
+ }
o << " </array>\n";
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
index 544cb0a..40c8a07 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
@@ -95,7 +95,7 @@ public:
Pass.TA.clearDiagnostic(diag::err_unavailable,
diag::err_unavailable_message,
E->getSelectorLoc(0));
- Pass.TA.replace(E->getSourceRange(), getNilString(Pass.Ctx));
+ Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
}
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index bcbc9e9..7db1a1c 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -145,7 +145,7 @@ public:
// when an exception is thrown.
Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
std::string str = " = ";
- str += getNilString(Pass.Ctx);
+ str += getNilString(Pass);
Pass.TA.insertAfterToken(RecRange.getEnd(), str);
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
index 98571c0..70370ec 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
@@ -58,7 +58,7 @@ public:
SourceRange ExprRange = ME->getSourceRange();
Pass.TA.insert(ExprRange.getBegin(), "if (!(self = ");
std::string retStr = ")) return ";
- retStr += getNilString(Pass.Ctx);
+ retStr += getNilString(Pass);
Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr);
}
return true;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
index 6ff7b6b..56d3af7 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/DenseSet.h"
@@ -212,11 +213,8 @@ bool trans::isGlobalVar(Expr *E) {
return false;
}
-StringRef trans::getNilString(ASTContext &Ctx) {
- if (Ctx.Idents.get("nil").hasMacroDefinition())
- return "nil";
- else
- return "0";
+StringRef trans::getNilString(MigrationPass &Pass) {
+ return Pass.SemaRef.PP.isMacroDefined("nil") ? "nil" : "0";
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
index 12551d2..7e3dd34 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
@@ -180,7 +180,7 @@ SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
bool hasSideEffects(Expr *E, ASTContext &Ctx);
bool isGlobalVar(Expr *E);
/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
-StringRef getNilString(ASTContext &Ctx);
+StringRef getNilString(MigrationPass &Pass);
template <typename BODY_TRANS>
class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp
index 55033b2..cff82e9 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
+#include "llvm/Bitcode/BitstreamReader.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
using namespace clang;
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index c9fb80c..fb96301 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -738,9 +738,9 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
- FirstLocalImport(), LastLocalImport(),
+ FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
SourceMgr(SM), LangOpts(LOpts),
- SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFile, SM)),
+ SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels), BuiltinInfo(builtins),
DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr),
@@ -866,6 +866,38 @@ void ASTContext::PrintStats() const {
BumpAlloc.PrintStats();
}
+void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
+ bool NotifyListeners) {
+ if (NotifyListeners)
+ if (auto *Listener = getASTMutationListener())
+ Listener->RedefinedHiddenDefinition(ND, M);
+
+ if (getLangOpts().ModulesLocalVisibility)
+ MergedDefModules[ND].push_back(M);
+ else
+ ND->setHidden(false);
+}
+
+void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
+ auto It = MergedDefModules.find(ND);
+ if (It == MergedDefModules.end())
+ return;
+
+ auto &Merged = It->second;
+ llvm::DenseSet<Module*> Found;
+ for (Module *&M : Merged)
+ if (!Found.insert(M).second)
+ M = nullptr;
+ Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
+}
+
+ExternCContextDecl *ASTContext::getExternCContextDecl() const {
+ if (!ExternCContext)
+ ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl());
+
+ return ExternCContext;
+}
+
RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
@@ -877,6 +909,8 @@ RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
NewDecl = RecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, Loc,
&Idents.get(Name));
NewDecl->setImplicit();
+ NewDecl->addAttr(TypeVisibilityAttr::CreateImplicit(
+ const_cast<ASTContext &>(*this), TypeVisibilityAttr::Default));
return NewDecl;
}
@@ -1326,7 +1360,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
}
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasGlobalStorage())
+ if (VD->hasGlobalStorage() && !ForAlignof)
Align = std::max(Align, getTargetInfo().getMinGlobalAlign());
}
}
@@ -1669,13 +1703,23 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
- if (const EnumType *ET = dyn_cast<EnumType>(TT))
- return getTypeInfo(ET->getDecl()->getIntegerType());
+ if (const EnumType *ET = dyn_cast<EnumType>(TT)) {
+ const EnumDecl *ED = ET->getDecl();
+ TypeInfo Info =
+ getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
+ if (unsigned AttrAlign = ED->getMaxAlignment()) {
+ Info.Align = AttrAlign;
+ Info.AlignIsRequired = true;
+ }
+ return Info;
+ }
const RecordType *RT = cast<RecordType>(TT);
- const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
+ const RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &Layout = getASTRecordLayout(RD);
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
+ AlignIsRequired = RD->hasAttr<AlignedAttr>();
break;
}
@@ -1742,6 +1786,17 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
return TypeInfo(Width, Align, AlignIsRequired);
}
+unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const {
+ unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
+ // Target ppc64 with QPX: simd default alignment for pointer to double is 32.
+ if ((getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64 ||
+ getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64le) &&
+ getTargetInfo().getABI() == "elfv1-qpx" &&
+ T->isSpecificBuiltinType(BuiltinType::Double))
+ SimdAlign = 256;
+ return SimdAlign;
+}
+
/// toCharUnitsFromBits - Convert a size in bits to a size in characters.
CharUnits ASTContext::toCharUnitsFromBits(int64_t BitSize) const {
return CharUnits::fromQuantity(BitSize / getCharWidth());
@@ -1778,13 +1833,20 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
TypeInfo TI = getTypeInfo(T);
unsigned ABIAlign = TI.Align;
+ T = T->getBaseElementTypeUnsafe();
+
+ // The preferred alignment of member pointers is that of a pointer.
+ if (T->isMemberPointerType())
+ return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
+
if (Target->getTriple().getArch() == llvm::Triple::xcore)
return ABIAlign; // Never overalign on XCore.
// Double and long long should be naturally aligned if possible.
- T = T->getBaseElementTypeUnsafe();
if (const ComplexType *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
+ if (const EnumType *ET = T->getAs<EnumType>())
+ T = ET->getDecl()->getIntegerType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
T->isSpecificBuiltinType(BuiltinType::ULongLong))
@@ -1796,6 +1858,13 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
return ABIAlign;
}
+/// getTargetDefaultAlignForAttributeAligned - Return the default alignment
+/// for __attribute__((aligned)) on this target, to be used if no alignment
+/// value is specified.
+unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const {
+ return getTargetInfo().getDefaultAlignForAttributeAligned();
+}
+
/// getAlignOfGlobalVar - Return the alignment in bits that should be given
/// to a global variable of the specified type.
unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
@@ -1808,6 +1877,16 @@ CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const {
return toCharUnitsFromBits(getAlignOfGlobalVar(T));
}
+CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
+ CharUnits Offset = CharUnits::Zero();
+ const ASTRecordLayout *Layout = &getASTRecordLayout(RD);
+ while (const CXXRecordDecl *Base = Layout->getBaseSharingVBPtr()) {
+ Offset += Layout->getBaseClassOffset(Base);
+ Layout = &getASTRecordLayout(Base);
+ }
+ return Offset;
+}
+
/// DeepCollectObjCIvars -
/// This routine first collects all declared, but not synthesized, ivars in
/// super class and then collects all ivars, including those synthesized for
@@ -1838,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.
@@ -1856,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);
}
}
@@ -3337,7 +3412,7 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
(void)CheckT;
}
- T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
+ T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon);
Types.push_back(T);
ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3361,7 +3436,7 @@ ASTContext::getParenType(QualType InnerType) const {
(void)CheckT;
}
- T = new (*this) ParenType(InnerType, Canon);
+ T = new (*this, TypeAlignment) ParenType(InnerType, Canon);
Types.push_back(T);
ParenTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3390,7 +3465,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
if (T)
return QualType(T, 0);
- T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
+ T = new (*this, TypeAlignment) DependentNameType(Keyword, NNS, Name, Canon);
Types.push_back(T);
DependentNameTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3492,7 +3567,8 @@ QualType ASTContext::getPackExpansionType(QualType Pattern,
}
}
- T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions);
+ T = new (*this, TypeAlignment)
+ PackExpansionType(Pattern, Canon, NumExpansions);
Types.push_back(T);
PackExpansionTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3500,9 +3576,9 @@ QualType ASTContext::getPackExpansionType(QualType Pattern,
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
-static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
- const ObjCProtocolDecl *RHS) {
- return LHS->getDeclName() < RHS->getDeclName();
+static int CmpProtocolNames(ObjCProtocolDecl *const *LHS,
+ ObjCProtocolDecl *const *RHS) {
+ return DeclarationName::compare((*LHS)->getDeclName(), (*RHS)->getDeclName());
}
static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
@@ -3513,7 +3589,7 @@ static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
return false;
for (unsigned i = 1; i != NumProtocols; ++i)
- if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) ||
+ if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 ||
Protocols[i]->getCanonicalDecl() != Protocols[i])
return false;
return true;
@@ -3524,7 +3600,7 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
// Sort protocols, keyed by name.
- std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
+ llvm::array_pod_sort(Protocols, ProtocolsEnd, CmpProtocolNames);
// Canonicalize.
for (unsigned I = 0, N = NumProtocols; I != N; ++I)
@@ -3538,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);
@@ -4325,6 +4445,19 @@ QualType ASTContext::getSignatureParameterType(QualType T) const {
return T.getUnqualifiedType();
}
+QualType ASTContext::getExceptionObjectType(QualType T) const {
+ // C++ [except.throw]p3:
+ // A throw-expression initializes a temporary object, called the exception
+ // object, the type of which is determined by removing any top-level
+ // cv-qualifiers from the static type of the operand of throw and adjusting
+ // the type from "array of T" or "function returning T" to "pointer to T"
+ // or "pointer to function returning T", [...]
+ T = getVariableArrayDecayedType(T);
+ if (T->isArrayType() || T->isFunctionType())
+ T = getDecayedType(T);
+ return T.getUnqualifiedType();
+}
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
@@ -4859,7 +4992,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
return getLangOpts().MSVCCompat && VD->isStaticDataMember() &&
VD->getType()->isIntegralOrEnumerationType() &&
- !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
+ VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit();
}
static inline
@@ -5530,16 +5663,10 @@ 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 += '{';
- const IdentifierInfo *II = OI->getIdentifier();
- S += II->getName();
+ S += OI->getObjCRuntimeNameAsString();
S += '=';
SmallVector<const ObjCIvarDecl*, 32> Ivars;
DeepCollectObjCIvars(OI, true, Ivars);
@@ -5582,7 +5709,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += '"';
for (const auto *I : OPT->quals()) {
S += '<';
- S += I->getNameAsString();
+ S += I->getObjCRuntimeNameAsString();
S += '>';
}
S += '"';
@@ -5606,7 +5733,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
if (cast<FieldDecl>(Ivars[i]) == FD) {
S += '{';
- S += OI->getIdentifier()->getName();
+ S += OI->getObjCRuntimeNameAsString();
S += '}';
return;
}
@@ -5624,10 +5751,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (OPT->getInterfaceDecl() &&
(FD || EncodingProperty || EncodeClassNames)) {
S += '"';
- S += OPT->getInterfaceDecl()->getIdentifier()->getName();
+ S += OPT->getInterfaceDecl()->getObjCRuntimeNameAsString();
for (const auto *I : OPT->quals()) {
S += '<';
- S += I->getNameAsString();
+ S += I->getObjCRuntimeNameAsString();
S += '>';
}
S += '"';
@@ -5829,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");
}
@@ -5846,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");
}
@@ -5859,6 +5986,7 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
= ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
&Idents.get("Protocol"),
+ /*typeParamList=*/nullptr,
/*PrevDecl=*/nullptr,
SourceLocation(), true);
}
@@ -6651,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;
}
@@ -6676,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;
@@ -6703,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;
+
+ 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;
+ }
- QualType Result = QualType(LHS, 0);
+ // 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();
}
@@ -6785,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.
@@ -6809,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;
@@ -6824,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) {
@@ -7544,7 +7896,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
break;
case 'U':
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
- assert(!Unsigned && "Can't use 'S' modifier multiple times!");
+ assert(!Unsigned && "Can't use 'U' modifier multiple times!");
Unsigned = true;
break;
case 'L':
@@ -7579,7 +7931,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
break;
case 'h':
assert(HowLong == 0 && !Signed && !Unsigned &&
- "Bad modifiers used with 'f'!");
+ "Bad modifiers used with 'h'!");
Type = Context.HalfTy;
break;
case 'f':
@@ -7806,6 +8158,9 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
ArgTypes.push_back(Ty);
}
+ if (Id == Builtin::BI__GetExceptionInfo)
+ return QualType();
+
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
@@ -7909,7 +8264,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
while (LexicalContext && !isa<FunctionDecl>(LexicalContext))
LexicalContext = LexicalContext->getLexicalParent();
- // Let the static local variable inherit it's linkage from the nearest
+ // Let the static local variable inherit its linkage from the nearest
// enclosing function.
if (LexicalContext)
StaticLocalLinkage =
@@ -8042,7 +8397,9 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
if (IsCXXMethod)
return ABI->getDefaultMethodCallConv(IsVariadic);
- return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C;
+ if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall;
+
+ return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
}
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
@@ -8161,6 +8518,31 @@ MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
return ABI->createMangleNumberingContext();
}
+const CXXConstructorDecl *
+ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) {
+ return ABI->getCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()));
+}
+
+void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) {
+ return ABI->addCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()),
+ cast<CXXConstructorDecl>(CD->getFirstDecl()));
+}
+
+void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) {
+ ABI->addDefaultArgExprForConstructor(
+ cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE);
+}
+
+Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) {
+ return ABI->getDefaultArgExprForConstructor(
+ cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx);
+}
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
index 000588f..dddaa5a 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
index ebf5e65..c95922b 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
+++ b/contrib/llvm/tools/clang/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);
@@ -508,6 +512,8 @@ namespace {
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
void VisitCXXConstructExpr(const CXXConstructExpr *Node);
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
+ void VisitCXXNewExpr(const CXXNewExpr *Node);
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
void VisitExprWithCleanups(const ExprWithCleanups *Node);
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
@@ -516,6 +522,7 @@ namespace {
VisitExpr(Node);
dumpDecl(Node->getLambdaClass());
}
+ void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
// ObjC
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
@@ -952,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.
//===----------------------------------------------------------------------===//
@@ -974,8 +993,14 @@ void ASTDumper::dumpDecl(const Decl *D) {
dumpSourceRange(D->getSourceRange());
OS << ' ';
dumpLocation(D->getLocation());
- if (Module *M = D->getOwningModule())
+ if (Module *M = D->getImportedOwningModule())
OS << " in " << M->getFullModuleName();
+ else if (Module *M = D->getLocalOwningModule())
+ OS << " in (local) " << M->getFullModuleName();
+ if (auto *ND = dyn_cast<NamedDecl>(D))
+ for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
+ const_cast<NamedDecl *>(ND)))
+ dumpChild([=] { OS << "also in " << M->getFullModuleName(); });
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->isHidden())
OS << " hidden";
@@ -1099,10 +1124,13 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
dumpDecl(*I);
- for (FunctionDecl::param_const_iterator I = D->param_begin(),
- E = D->param_end();
- I != E; ++I)
- dumpDecl(*I);
+ if (!D->param_begin() && D->getNumParams())
+ dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
+ else
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end();
+ I != E; ++I)
+ dumpDecl(*I);
if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D))
for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
@@ -1445,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();
@@ -1470,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());
@@ -1587,8 +1637,8 @@ void ASTDumper::dumpStmt(const Stmt *S) {
ConstStmtVisitor<ASTDumper>::Visit(S);
- for (Stmt::const_child_range CI = S->children(); CI; ++CI)
- dumpStmt(*CI);
+ for (const Stmt *SubStmt : S->children())
+ dumpStmt(SubStmt);
});
}
@@ -1817,6 +1867,9 @@ void ASTDumper::VisitUnaryExprOrTypeTraitExpr(
case UETT_VecStep:
OS << " vec_step";
break;
+ case UETT_OpenMPRequiredSimdAlign:
+ OS << " __builtin_omp_required_simd_align";
+ break;
}
if (Node->isArgumentType())
dumpType(Node->getArgumentType());
@@ -1913,6 +1966,32 @@ void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) {
dumpCXXTemporary(Node->getTemporary());
}
+void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
+ VisitExpr(Node);
+ if (Node->isGlobalNew())
+ OS << " global";
+ if (Node->isArray())
+ OS << " array";
+ if (Node->getOperatorNew()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorNew());
+ }
+ // We could dump the deallocation function used in case of error, but it's
+ // usually not that interesting.
+}
+
+void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
+ VisitExpr(Node);
+ if (Node->isGlobalDelete())
+ OS << " global";
+ if (Node->isArrayForm())
+ OS << " array";
+ if (Node->getOperatorDelete()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorDelete());
+ }
+}
+
void
ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) {
VisitExpr(Node);
@@ -1934,6 +2013,13 @@ void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
OS << ")";
}
+void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
+ VisitExpr(Node);
+ dumpPointer(Node->getPack());
+ dumpName(Node->getPack());
+}
+
+
//===----------------------------------------------------------------------===//
// Obj-C Expressions
//===----------------------------------------------------------------------===//
@@ -2255,6 +2341,11 @@ LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
P.dumpStmt(this);
}
+LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
+ ASTDumper P(OS, nullptr, nullptr);
+ P.dumpStmt(this);
+}
+
LLVM_DUMP_METHOD void Stmt::dump() const {
ASTDumper P(llvm::errs(), nullptr, nullptr);
P.dumpStmt(this);
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 2442e8e..35c0f69 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -67,6 +67,7 @@ namespace clang {
// FIXME: DependentDecltypeType
QualType VisitRecordType(const RecordType *T);
QualType VisitEnumType(const EnumType *T);
+ QualType VisitAttributedType(const AttributedType *T);
// FIXME: TemplateTypeParmType
// FIXME: SubstTemplateTypeParmType
QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
@@ -80,7 +81,7 @@ namespace clang {
// Importing declarations
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
- SourceLocation &Loc);
+ NamedDecl *&ToD, SourceLocation &Loc);
void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
@@ -149,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);
@@ -167,7 +171,44 @@ namespace clang {
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
// Importing statements
+ DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
+
Stmt *VisitStmt(Stmt *S);
+ Stmt *VisitDeclStmt(DeclStmt *S);
+ Stmt *VisitNullStmt(NullStmt *S);
+ Stmt *VisitCompoundStmt(CompoundStmt *S);
+ Stmt *VisitCaseStmt(CaseStmt *S);
+ Stmt *VisitDefaultStmt(DefaultStmt *S);
+ Stmt *VisitLabelStmt(LabelStmt *S);
+ Stmt *VisitAttributedStmt(AttributedStmt *S);
+ Stmt *VisitIfStmt(IfStmt *S);
+ Stmt *VisitSwitchStmt(SwitchStmt *S);
+ Stmt *VisitWhileStmt(WhileStmt *S);
+ Stmt *VisitDoStmt(DoStmt *S);
+ Stmt *VisitForStmt(ForStmt *S);
+ Stmt *VisitGotoStmt(GotoStmt *S);
+ Stmt *VisitIndirectGotoStmt(IndirectGotoStmt *S);
+ Stmt *VisitContinueStmt(ContinueStmt *S);
+ Stmt *VisitBreakStmt(BreakStmt *S);
+ Stmt *VisitReturnStmt(ReturnStmt *S);
+ // FIXME: GCCAsmStmt
+ // FIXME: MSAsmStmt
+ // FIXME: SEHExceptStmt
+ // FIXME: SEHFinallyStmt
+ // FIXME: SEHTryStmt
+ // FIXME: SEHLeaveStmt
+ // FIXME: CapturedStmt
+ Stmt *VisitCXXCatchStmt(CXXCatchStmt *S);
+ Stmt *VisitCXXTryStmt(CXXTryStmt *S);
+ Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S);
+ // FIXME: MSDependentExistsStmt
+ Stmt *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ Stmt *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
+ Stmt *VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
+ Stmt *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
+ Stmt *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ Stmt *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
+ Stmt *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
// Importing expressions
Expr *VisitExpr(Expr *E);
@@ -181,6 +222,9 @@ namespace clang {
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+ Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
+ Expr *VisitMemberExpr(MemberExpr *E);
+ Expr *VisitCallExpr(CallExpr *E);
};
}
using namespace clang;
@@ -1724,6 +1768,27 @@ QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
return Importer.getToContext().getTagDeclType(ToDecl);
}
+QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
+ QualType FromModifiedType = T->getModifiedType();
+ QualType FromEquivalentType = T->getEquivalentType();
+ QualType ToModifiedType;
+ QualType ToEquivalentType;
+
+ if (!FromModifiedType.isNull()) {
+ ToModifiedType = Importer.Import(FromModifiedType);
+ if (ToModifiedType.isNull())
+ return QualType();
+ }
+ if (!FromEquivalentType.isNull()) {
+ ToEquivalentType = Importer.Import(FromEquivalentType);
+ if (ToEquivalentType.isNull())
+ return QualType();
+ }
+
+ return Importer.getToContext().getAttributedType(T->getAttrKind(),
+ ToModifiedType, ToEquivalentType);
+}
+
QualType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
TemplateName ToTemplate = Importer.Import(T->getTemplateName());
@@ -1779,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
@@ -1788,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
@@ -1808,6 +1882,7 @@ ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC,
DeclarationName &Name,
+ NamedDecl *&ToD,
SourceLocation &Loc) {
// Import the context of this declaration.
DC = Importer.ImportContext(D->getDeclContext());
@@ -1828,6 +1903,7 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
// Import the location of this declaration.
Loc = Importer.Import(D->getLocation());
+ ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
return false;
}
@@ -2009,7 +2085,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
ImportDefinitionKind Kind) {
- if (To->getDefinition())
+ if (To->getAnyInitializer())
return false;
// FIXME: Can we really import any initializer? Alternatively, we could force
@@ -2239,8 +2315,11 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
NamespaceDecl *MergeWithNamespace = nullptr;
if (!Name) {
@@ -2307,8 +2386,11 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
@@ -2381,8 +2463,11 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what enum name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
@@ -2466,8 +2551,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what structure name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
@@ -2592,8 +2680,11 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2648,8 +2739,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
@@ -2741,10 +2835,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Create the imported function.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
FunctionDecl *ToFunction = nullptr;
+ SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
@@ -2753,7 +2848,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
D->isImplicit());
@@ -2761,7 +2856,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
= dyn_cast<CXXConversionDecl>(D)) {
ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit(),
@@ -2770,7 +2865,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
Method->getStorageClass(),
Method->isInlineSpecified(),
@@ -2778,7 +2873,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
Importer.Import(D->getLocEnd()));
} else {
ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo, D->getStorageClass(),
D->isInlineSpecified(),
D->hasWrittenPrototype(),
@@ -2809,6 +2904,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setType(T);
}
+ // Import the body, if any.
+ if (Stmt *FromBody = D->getBody()) {
+ if (Stmt *ToBody = Importer.Import(FromBody)) {
+ ToFunction->setBody(ToBody);
+ }
+ }
+
// FIXME: Other bits to merge?
// Add this function to the lexical context.
@@ -2855,8 +2957,11 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2911,8 +3016,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2978,8 +3086,11 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3028,8 +3139,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a variable in our own ("to") context with the same name and
// in the same context as the variable we're importing.
@@ -3137,6 +3251,10 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
Importer.Imported(D, ToVar);
LexicalDC->addDeclInternal(ToVar);
+ if (!D->isFileVarDecl() &&
+ D->isUsed())
+ ToVar->setIsUsed();
+
// Merge the initializer.
if (ImportDefinition(D, ToVar))
return nullptr;
@@ -3196,6 +3314,10 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
T, TInfo, D->getStorageClass(),
/*FIXME: Default argument*/nullptr);
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
+
+ if (D->isUsed())
+ ToParm->setIsUsed();
+
return Importer.Imported(D, ToParm);
}
@@ -3204,8 +3326,11 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
@@ -3310,13 +3435,45 @@ 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;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCInterfaceDecl *ToInterface
= cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
@@ -3334,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;
@@ -3439,8 +3601,11 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3544,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
@@ -3597,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
@@ -3614,8 +3798,11 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = nullptr;
@@ -3634,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;
@@ -3769,8 +3961,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3797,8 +3992,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
}
// Import the type.
- TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());
- if (!T)
+ TypeSourceInfo *TSI = Importer.Import(D->getTypeSourceInfo());
+ if (!TSI)
return nullptr;
// Create the new property.
@@ -3807,7 +4002,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(D->getAtLoc()),
Importer.Import(D->getLParenLoc()),
- T,
+ Importer.Import(D->getType()),
+ TSI,
D->getPropertyImplementation());
Importer.Imported(D, ToProperty);
ToProperty->setLexicalDeclContext(LexicalDC);
@@ -4000,8 +4196,11 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
@@ -4188,8 +4387,11 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// We may already have a template of the same name; try to find and match it.
assert(!DC->isFunctionOrMethod() &&
@@ -4371,10 +4573,457 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// Import Statements
//----------------------------------------------------------------------------
-Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
- Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
- << S->getStmtClassName();
- return nullptr;
+DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) {
+ if (DG.isNull())
+ return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
+ size_t NumDecls = DG.end() - DG.begin();
+ SmallVector<Decl *, 1> ToDecls(NumDecls);
+ auto &_Importer = this->Importer;
+ std::transform(DG.begin(), DG.end(), ToDecls.begin(),
+ [&_Importer](Decl *D) -> Decl * {
+ return _Importer.Import(D);
+ });
+ return DeclGroupRef::Create(Importer.getToContext(),
+ ToDecls.begin(),
+ NumDecls);
+}
+
+ Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return nullptr;
+ }
+
+Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
+ DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
+ for (Decl *ToD : ToDG) {
+ if (!ToD)
+ return nullptr;
+ }
+ SourceLocation ToStartLoc = Importer.Import(S->getStartLoc());
+ SourceLocation ToEndLoc = Importer.Import(S->getEndLoc());
+ return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc);
+}
+
+Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
+ SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc());
+ return new (Importer.getToContext()) NullStmt(ToSemiLoc,
+ S->hasLeadingEmptyMacro());
+}
+
+Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
+ SmallVector<Stmt *, 4> ToStmts(S->size());
+ auto &_Importer = this->Importer;
+ std::transform(S->body_begin(), S->body_end(), ToStmts.begin(),
+ [&_Importer](Stmt *CS) -> Stmt * {
+ return _Importer.Import(CS);
+ });
+ for (Stmt *ToS : ToStmts) {
+ if (!ToS)
+ return nullptr;
+ }
+ SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
+ SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc());
+ return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(),
+ ToStmts,
+ ToLBraceLoc, ToRBraceLoc);
+}
+
+Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
+ Expr *ToLHS = Importer.Import(S->getLHS());
+ if (!ToLHS)
+ return nullptr;
+ Expr *ToRHS = Importer.Import(S->getRHS());
+ if (!ToRHS && S->getRHS())
+ return nullptr;
+ SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
+ SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS,
+ ToCaseLoc, ToEllipsisLoc,
+ ToColonLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
+ SourceLocation ToDefaultLoc = Importer.Import(S->getDefaultLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) DefaultStmt(ToDefaultLoc, ToColonLoc,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
+ SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc());
+ LabelDecl *ToLabelDecl =
+ cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
+ if (!ToLabelDecl && S->getDecl())
+ return nullptr;
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) LabelStmt(ToIdentLoc, ToLabelDecl,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
+ SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc());
+ ArrayRef<const Attr*> FromAttrs(S->getAttrs());
+ SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
+ ASTContext &_ToContext = Importer.getToContext();
+ std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(),
+ [&_ToContext](const Attr *A) -> const Attr * {
+ return A->clone(_ToContext);
+ });
+ for (const Attr *ToA : ToAttrs) {
+ if (!ToA)
+ return nullptr;
+ }
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc,
+ ToAttrs, ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) {
+ SourceLocation ToIfLoc = Importer.Import(S->getIfLoc());
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ Stmt *ToThenStmt = Importer.Import(S->getThen());
+ if (!ToThenStmt && S->getThen())
+ return nullptr;
+ SourceLocation ToElseLoc = Importer.Import(S->getElseLoc());
+ Stmt *ToElseStmt = Importer.Import(S->getElse());
+ if (!ToElseStmt && S->getElse())
+ return nullptr;
+ return new (Importer.getToContext()) IfStmt(Importer.getToContext(),
+ ToIfLoc, ToConditionVariable,
+ ToCondition, ToThenStmt,
+ ToElseLoc, ToElseStmt);
+}
+
+Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt(
+ Importer.getToContext(), ToConditionVariable,
+ ToCondition);
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ ToStmt->setBody(ToBody);
+ ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc()));
+ // Now we have to re-chain the cases.
+ SwitchCase *LastChainedSwitchCase = nullptr;
+ for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
+ SC = SC->getNextSwitchCase()) {
+ SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
+ if (!ToSC)
+ return nullptr;
+ if (LastChainedSwitchCase)
+ LastChainedSwitchCase->setNextSwitchCase(ToSC);
+ else
+ ToStmt->setSwitchCaseList(ToSC);
+ LastChainedSwitchCase = ToSC;
+ }
+ return ToStmt;
+}
+
+Stmt *ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ return new (Importer.getToContext()) WhileStmt(Importer.getToContext(),
+ ToConditionVariable,
+ ToCondition, ToBody,
+ ToWhileLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDoStmt(DoStmt *S) {
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ SourceLocation ToDoLoc = Importer.Import(S->getDoLoc());
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) DoStmt(ToBody, ToCondition,
+ ToDoLoc, ToWhileLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitForStmt(ForStmt *S) {
+ Stmt *ToInit = Importer.Import(S->getInit());
+ if (!ToInit && S->getInit())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToInc = Importer.Import(S->getInc());
+ if (!ToInc && S->getInc())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToLParenLoc = Importer.Import(S->getLParenLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ForStmt(Importer.getToContext(),
+ ToInit, ToCondition,
+ ToConditionVariable,
+ ToInc, ToBody,
+ ToForLoc, ToLParenLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
+ LabelDecl *ToLabel = nullptr;
+ if (LabelDecl *FromLabel = S->getLabel()) {
+ ToLabel = dyn_cast_or_null<LabelDecl>(Importer.Import(FromLabel));
+ if (!ToLabel)
+ return nullptr;
+ }
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToLabelLoc = Importer.Import(S->getLabelLoc());
+ return new (Importer.getToContext()) GotoStmt(ToLabel,
+ ToGotoLoc, ToLabelLoc);
+}
+
+Stmt *ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToStarLoc = Importer.Import(S->getStarLoc());
+ Expr *ToTarget = Importer.Import(S->getTarget());
+ if (!ToTarget && S->getTarget())
+ return nullptr;
+ return new (Importer.getToContext()) IndirectGotoStmt(ToGotoLoc, ToStarLoc,
+ ToTarget);
+}
+
+Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
+ SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc());
+ return new (Importer.getToContext()) ContinueStmt(ToContinueLoc);
+}
+
+Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
+ SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc());
+ return new (Importer.getToContext()) BreakStmt(ToBreakLoc);
+}
+
+Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
+ SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc());
+ Expr *ToRetExpr = Importer.Import(S->getRetValue());
+ if (!ToRetExpr && S->getRetValue())
+ return nullptr;
+ VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate());
+ VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
+ if (!ToNRVOCandidate && NRVOCandidate)
+ return nullptr;
+ return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr,
+ ToNRVOCandidate);
+}
+
+Stmt *ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ SourceLocation ToCatchLoc = Importer.Import(S->getCatchLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getExceptionDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToHandlerBlock = Importer.Import(S->getHandlerBlock());
+ if (!ToHandlerBlock && S->getHandlerBlock())
+ return nullptr;
+ return new (Importer.getToContext()) CXXCatchStmt(ToCatchLoc,
+ ToExceptionDecl,
+ ToHandlerBlock);
+}
+
+Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
+ SourceLocation ToTryLoc = Importer.Import(S->getTryLoc());
+ Stmt *ToTryBlock = Importer.Import(S->getTryBlock());
+ if (!ToTryBlock && S->getTryBlock())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers());
+ for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) {
+ CXXCatchStmt *FromHandler = S->getHandler(HI);
+ if (Stmt *ToHandler = Importer.Import(FromHandler))
+ ToHandlers[HI] = ToHandler;
+ else
+ return nullptr;
+ }
+ return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock,
+ ToHandlers);
+}
+
+Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
+ DeclStmt *ToRange =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt()));
+ if (!ToRange && S->getRangeStmt())
+ return nullptr;
+ DeclStmt *ToBeginEnd =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginEndStmt()));
+ if (!ToBeginEnd && S->getBeginEndStmt())
+ return nullptr;
+ Expr *ToCond = Importer.Import(S->getCond());
+ if (!ToCond && S->getCond())
+ return nullptr;
+ Expr *ToInc = Importer.Import(S->getInc());
+ if (!ToInc && S->getInc())
+ return nullptr;
+ DeclStmt *ToLoopVar =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt()));
+ if (!ToLoopVar && S->getLoopVarStmt())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBeginEnd,
+ ToCond, ToInc,
+ ToLoopVar, ToBody,
+ ToForLoc, ToColonLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ Stmt *ToElem = Importer.Import(S->getElement());
+ if (!ToElem && S->getElement())
+ return nullptr;
+ Expr *ToCollect = Importer.Import(S->getCollection());
+ if (!ToCollect && S->getCollection())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ObjCForCollectionStmt(ToElem,
+ ToCollect,
+ ToBody, ToForLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ SourceLocation ToAtCatchLoc = Importer.Import(S->getAtCatchLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getCatchParamDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToBody = Importer.Import(S->getCatchBody());
+ if (!ToBody && S->getCatchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtCatchStmt(ToAtCatchLoc,
+ ToRParenLoc,
+ ToExceptionDecl,
+ ToBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ SourceLocation ToAtFinallyLoc = Importer.Import(S->getAtFinallyLoc());
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyBody());
+ if (!ToAtFinallyStmt && S->getFinallyBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtFinallyStmt(ToAtFinallyLoc,
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc());
+ Stmt *ToAtTryStmt = Importer.Import(S->getTryBody());
+ if (!ToAtTryStmt && S->getTryBody())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
+ for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
+ ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI);
+ if (Stmt *ToCatchStmt = Importer.Import(FromCatchStmt))
+ ToCatchStmts[CI] = ToCatchStmt;
+ else
+ return nullptr;
+ }
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt());
+ if (!ToAtFinallyStmt && S->getFinallyStmt())
+ return nullptr;
+ return ObjCAtTryStmt::Create(Importer.getToContext(),
+ ToAtTryLoc, ToAtTryStmt,
+ ToCatchStmts.begin(), ToCatchStmts.size(),
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt
+ (ObjCAtSynchronizedStmt *S) {
+ SourceLocation ToAtSynchronizedLoc =
+ Importer.Import(S->getAtSynchronizedLoc());
+ Expr *ToSynchExpr = Importer.Import(S->getSynchExpr());
+ if (!ToSynchExpr && S->getSynchExpr())
+ return nullptr;
+ Stmt *ToSynchBody = Importer.Import(S->getSynchBody());
+ if (!ToSynchBody && S->getSynchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
+ ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ SourceLocation ToAtThrowLoc = Importer.Import(S->getThrowLoc());
+ Expr *ToThrow = Importer.Import(S->getThrowExpr());
+ if (!ToThrow && S->getThrowExpr())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtThrowStmt(ToAtThrowLoc, ToThrow);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAutoreleasePoolStmt
+ (ObjCAutoreleasePoolStmt *S) {
+ SourceLocation ToAtLoc = Importer.Import(S->getAtLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(ToAtLoc,
+ ToSubStmt);
}
//----------------------------------------------------------------------------
@@ -4585,6 +5234,107 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
Importer.Import(E->getRParenLoc()));
}
+Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ CXXConstructorDecl *ToCCD =
+ dyn_cast<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
+ if (!ToCCD && E->getConstructor())
+ return nullptr;
+
+ size_t NumArgs = E->getNumArgs();
+ SmallVector<Expr *, 1> ToArgs(NumArgs);
+ ASTImporter &_Importer = Importer;
+ std::transform(E->arg_begin(), E->arg_end(), ToArgs.begin(),
+ [&_Importer](Expr *AE) -> Expr * {
+ return _Importer.Import(AE);
+ });
+ for (Expr *ToA : ToArgs) {
+ if (!ToA)
+ return nullptr;
+ }
+
+ return CXXConstructExpr::Create(Importer.getToContext(), T,
+ Importer.Import(E->getLocation()),
+ ToCCD, E->isElidable(),
+ ToArgs, E->hadMultipleCandidates(),
+ E->isListInitialization(),
+ E->isStdInitListInitialization(),
+ E->requiresZeroInitialization(),
+ E->getConstructionKind(),
+ Importer.Import(E->getParenOrBraceRange()));
+}
+
+Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToBase = Importer.Import(E->getBase());
+ if (!ToBase && E->getBase())
+ return nullptr;
+
+ ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
+ if (!ToMember && E->getMemberDecl())
+ return nullptr;
+
+ DeclAccessPair ToFoundDecl = DeclAccessPair::make(
+ dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())),
+ E->getFoundDecl().getAccess());
+
+ DeclarationNameInfo ToMemberNameInfo(
+ Importer.Import(E->getMemberNameInfo().getName()),
+ Importer.Import(E->getMemberNameInfo().getLoc()));
+
+ if (E->hasExplicitTemplateArgs()) {
+ return nullptr; // FIXME: handle template arguments
+ }
+
+ return MemberExpr::Create(Importer.getToContext(), ToBase,
+ E->isArrow(),
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()),
+ ToMember, ToFoundDecl, ToMemberNameInfo,
+ nullptr, T, E->getValueKind(),
+ E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToCallee = Importer.Import(E->getCallee());
+ if (!ToCallee && E->getCallee())
+ return nullptr;
+
+ unsigned NumArgs = E->getNumArgs();
+
+ llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) {
+ Expr *FromArg = E->getArg(ai);
+ Expr *ToArg = Importer.Import(FromArg);
+ if (!ToArg)
+ return nullptr;
+ ToArgs[ai] = ToArg;
+ }
+
+ Expr **ToArgs_Copied = new (Importer.getToContext())
+ Expr*[NumArgs];
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
+ ToArgs_Copied[ai] = ToArgs[ai];
+
+ return new (Importer.getToContext())
+ CallExpr(Importer.getToContext(), ToCallee,
+ ArrayRef<Expr*>(ToArgs_Copied, NumArgs), T, E->getValueKind(),
+ Importer.Import(E->getRParenLoc()));
+}
+
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport)
@@ -4633,7 +5383,18 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return nullptr;
return ToContext.getTrivialTypeSourceInfo(T,
- FromTSI->getTypeLoc().getLocStart());
+ Import(FromTSI->getTypeLoc().getLocStart()));
+}
+
+Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
+ llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
+ if (Pos != ImportedDecls.end()) {
+ Decl *ToD = Pos->second;
+ ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD);
+ return ToD;
+ } else {
+ return nullptr;
+ }
}
Decl *ASTImporter::Import(Decl *FromD) {
@@ -4927,8 +5688,9 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
FileID ToFileID = Import(Decomposed.first);
if (ToFileID.isInvalid())
return SourceLocation();
- return ToSM.getLocForStartOfFile(ToFileID)
- .getLocWithOffset(Decomposed.second);
+ SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID)
+ .getLocWithOffset(Decomposed.second);
+ return ret;
}
SourceRange ASTImporter::Import(SourceRange FromRange) {
@@ -4952,7 +5714,7 @@ FileID ASTImporter::Import(FileID FromID) {
// Map the FileID for to the "to" source manager.
FileID ToID;
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
- if (Cache->OrigEntry) {
+ if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
// disk again
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
index 0bf6bcd..cb60870 100644
--- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains out-of-line virtual methods for Attr classes.
+// This file contains out-of-line methods for Attr classes.
//
//===----------------------------------------------------------------------===//
@@ -18,10 +18,4 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
-Attr::~Attr() { }
-
-void InheritableAttr::anchor() { }
-
-void InheritableParamAttr::anchor() { }
-
#include "clang/AST/AttrImpl.inc"
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
index 8e9e358..dad2264 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h
+++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
@@ -20,6 +20,8 @@
namespace clang {
class ASTContext;
+class CXXConstructorDecl;
+class Expr;
class MemberPointerType;
class MangleNumberingContext;
@@ -41,6 +43,20 @@ public:
/// Returns a new mangling number context for this C++ ABI.
virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
+
+ /// Adds a mapping from class to copy constructor for this C++ ABI.
+ virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *,
+ CXXConstructorDecl *) = 0;
+
+ /// Retrieves the mapping from class to copy constructor for this C++ ABI.
+ virtual const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0;
+
+ virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) = 0;
+
+ virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) = 0;
};
/// Creates an instance of a C++ ABI class.
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
index 6e80ee7..800c8f8 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -318,48 +318,36 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
//
// FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
// way to make it any faster.
- for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end();
- P != PEnd; /* increment in loop */) {
- bool Hidden = false;
-
- for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end();
- PE != PEEnd && !Hidden; ++PE) {
- if (PE->Base->isVirtual()) {
- CXXRecordDecl *VBase = nullptr;
- if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>())
- VBase = cast<CXXRecordDecl>(Record->getDecl());
- if (!VBase)
+ Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
+ for (const CXXBasePathElement &PE : Path) {
+ if (!PE.Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *VBase = nullptr;
+ if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
+ VBase = cast<CXXRecordDecl>(Record->getDecl());
+ if (!VBase)
+ break;
+
+ // The declaration(s) we found along this path were found in a
+ // subobject of a virtual base. Check whether this virtual
+ // base is a subobject of any other path; if so, then the
+ // declaration in this path are hidden by that patch.
+ for (const CXXBasePath &HidingP : Paths) {
+ CXXRecordDecl *HidingClass = nullptr;
+ if (const RecordType *Record =
+ HidingP.back().Base->getType()->getAs<RecordType>())
+ HidingClass = cast<CXXRecordDecl>(Record->getDecl());
+ if (!HidingClass)
break;
- // The declaration(s) we found along this path were found in a
- // subobject of a virtual base. Check whether this virtual
- // base is a subobject of any other path; if so, then the
- // declaration in this path are hidden by that patch.
- for (CXXBasePaths::paths_iterator HidingP = Paths.begin(),
- HidingPEnd = Paths.end();
- HidingP != HidingPEnd;
- ++HidingP) {
- CXXRecordDecl *HidingClass = nullptr;
- if (const RecordType *Record
- = HidingP->back().Base->getType()->getAs<RecordType>())
- HidingClass = cast<CXXRecordDecl>(Record->getDecl());
- if (!HidingClass)
- break;
-
- if (HidingClass->isVirtuallyDerivedFrom(VBase)) {
- Hidden = true;
- break;
- }
- }
+ if (HidingClass->isVirtuallyDerivedFrom(VBase))
+ return true;
}
}
+ return false;
+ });
- if (Hidden)
- P = Paths.Paths.erase(P);
- else
- ++P;
- }
-
return true;
}
@@ -569,18 +557,14 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// overrider. To do so, we dig down to the original virtual
// functions using data recursion and update all of the methods it
// overrides.
- typedef std::pair<CXXMethodDecl::method_iterator,
- CXXMethodDecl::method_iterator> OverriddenMethods;
+ typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
+ OverriddenMethods;
SmallVector<OverriddenMethods, 4> Stack;
- Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(),
- CanonM->end_overridden_methods()));
+ Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(),
+ CanonM->end_overridden_methods()));
while (!Stack.empty()) {
- OverriddenMethods OverMethods = Stack.back();
- Stack.pop_back();
-
- for (; OverMethods.first != OverMethods.second; ++OverMethods.first) {
- const CXXMethodDecl *CanonOM
- = cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl());
+ for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
+ const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
// C++ [class.virtual]p2:
// A virtual member function C::vf of a class object S is
@@ -601,8 +585,8 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// Continue recursion to the methods that this virtual method
// overrides.
- Stack.push_back(std::make_pair(CanonOM->begin_overridden_methods(),
- CanonOM->end_overridden_methods()));
+ Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(),
+ CanonOM->end_overridden_methods()));
}
}
@@ -630,54 +614,32 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
// Weed out any final overriders that come from virtual base class
// subobjects that were hidden by other subobjects along any path.
// This is the final-overrider variant of C++ [class.member.lookup]p10.
- for (CXXFinalOverriderMap::iterator OM = FinalOverriders.begin(),
- OMEnd = FinalOverriders.end();
- OM != OMEnd;
- ++OM) {
- for (OverridingMethods::iterator SO = OM->second.begin(),
- SOEnd = OM->second.end();
- SO != SOEnd;
- ++SO) {
- SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO->second;
+ for (auto &OM : FinalOverriders) {
+ for (auto &SO : OM.second) {
+ SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second;
if (Overriding.size() < 2)
continue;
- for (SmallVectorImpl<UniqueVirtualMethod>::iterator
- Pos = Overriding.begin(), PosEnd = Overriding.end();
- Pos != PosEnd;
- /* increment in loop */) {
- if (!Pos->InVirtualSubobject) {
- ++Pos;
- continue;
- }
+ auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) {
+ if (!M.InVirtualSubobject)
+ return false;
// We have an overriding method in a virtual base class
// subobject (or non-virtual base class subobject thereof);
// determine whether there exists an other overriding method
// in a base class subobject that hides the virtual base class
// subobject.
- bool Hidden = false;
- for (SmallVectorImpl<UniqueVirtualMethod>::iterator
- OP = Overriding.begin(), OPEnd = Overriding.end();
- OP != OPEnd && !Hidden;
- ++OP) {
- if (Pos == OP)
- continue;
-
- if (OP->Method->getParent()->isVirtuallyDerivedFrom(
- const_cast<CXXRecordDecl *>(Pos->InVirtualSubobject)))
- Hidden = true;
- }
-
- if (Hidden) {
- // The current overriding function is hidden by another
- // overriding function; remove this one.
- Pos = Overriding.erase(Pos);
- PosEnd = Overriding.end();
- } else {
- ++Pos;
- }
- }
+ for (const UniqueVirtualMethod &OP : Overriding)
+ if (&M != &OP &&
+ OP.Method->getParent()->isVirtuallyDerivedFrom(
+ M.InVirtualSubobject))
+ return true;
+ return false;
+ };
+
+ Overriding.erase(
+ std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
+ Overriding.end());
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
index 06a08bd..98b7e36 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
@@ -514,6 +514,12 @@ void Lexer::lexVerbatimBlockBody(Token &T) {
if (CommentState == LCS_InsideCComment)
skipLineStartingDecorations();
+ if (BufferPtr == CommentEnd) {
+ formTokenWithChars(T, BufferPtr, tok::verbatim_block_line);
+ T.setVerbatimBlockText("");
+ return;
+ }
+
lexVerbatimBlockFirstLine(T);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index dc08d23..ea4b2f5 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -44,6 +44,12 @@ bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
}
+TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
+ : Decl(TranslationUnit, nullptr, SourceLocation()),
+ DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {
+ Hidden = Ctx.getLangOpts().ModulesLocalVisibility;
+}
+
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
@@ -894,13 +900,13 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
// If the type of the function uses a type with unique-external
// linkage, it's not legally usable from outside this translation unit.
- // But only look at the type-as-written. If this function has an auto-deduced
- // return type, we can't compute the linkage of that type because it could
- // require looking at the linkage of this function, and we don't need this
- // for correctness because the type is not part of the function's
- // signature.
- // FIXME: This is a hack. We should be able to solve this circularity and the
- // one in getLVForNamespaceScopeDecl for Functions some other way.
+ // But only look at the type-as-written. If this function has an
+ // auto-deduced return type, we can't compute the linkage of that type
+ // because it could require looking at the linkage of this function, and we
+ // don't need this for correctness because the type is not part of the
+ // function's signature.
+ // FIXME: This is a hack. We should be able to solve this circularity and
+ // the one in getLVForNamespaceScopeDecl for Functions some other way.
{
QualType TypeAsWritten = MD->getType();
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
@@ -1445,74 +1451,127 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
printName(OS);
}
-bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
- assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) {
+ // For method declarations, we never replace.
+ if (ObjCMethodDecl::classofKind(NewK))
+ return false;
- // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
- // We want to keep it, unless it nominates same namespace.
- if (getKind() == Decl::UsingDirective) {
- return cast<UsingDirectiveDecl>(this)->getNominatedNamespace()
- ->getOriginalNamespace() ==
- cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
- ->getOriginalNamespace();
+ if (OldK == NewK)
+ return true;
+
+ // A compatibility alias for a class can be replaced by an interface.
+ if (ObjCCompatibleAliasDecl::classofKind(OldK) &&
+ ObjCInterfaceDecl::classofKind(NewK))
+ return true;
+
+ // A typedef-declaration, alias-declaration, or Objective-C class declaration
+ // can replace another declaration of the same type. Semantic analysis checks
+ // that we have matching types.
+ if ((TypedefNameDecl::classofKind(OldK) ||
+ ObjCInterfaceDecl::classofKind(OldK)) &&
+ (TypedefNameDecl::classofKind(NewK) ||
+ ObjCInterfaceDecl::classofKind(NewK)))
+ return true;
+
+ // Otherwise, a kind mismatch implies that the declaration is not replaced.
+ return false;
+}
+
+template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
+ return true;
+}
+static bool isRedeclarableImpl(...) { return false; }
+static bool isRedeclarable(Decl::Kind K) {
+ switch (K) {
+#define DECL(Type, Base) \
+ case Decl::Type: \
+ return isRedeclarableImpl((Type##Decl *)nullptr);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
}
+ llvm_unreachable("unknown decl kind");
+}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
- // For function declarations, we keep track of redeclarations.
- return FD->getPreviousDecl() == OldD;
+bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
+ assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
- // For function templates, the underlying function declarations are linked.
- if (const FunctionTemplateDecl *FunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(this))
- if (const FunctionTemplateDecl *OldFunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(OldD))
- return FunctionTemplate->getTemplatedDecl()
- ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
-
- // For method declarations, we keep track of redeclarations.
- if (isa<ObjCMethodDecl>(this))
+ // Never replace one imported declaration with another; we need both results
+ // when re-exporting.
+ if (OldD->isFromASTFile() && isFromASTFile())
return false;
- // FIXME: Is this correct if one of the decls comes from an inline namespace?
- if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
- return true;
+ if (!isKindReplaceableBy(OldD->getKind(), getKind()))
+ return false;
+
+ // Inline namespaces can give us two declarations with the same
+ // name and kind in the same scope but different contexts; we should
+ // keep both declarations in this case.
+ if (!this->getDeclContext()->getRedeclContext()->Equals(
+ OldD->getDeclContext()->getRedeclContext()))
+ return false;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
+ // For function declarations, we keep track of redeclarations.
+ // FIXME: This returns false for functions that should in fact be replaced.
+ // Instead, perform some kind of type check?
+ if (FD->getPreviousDecl() != OldD)
+ return false;
- if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
- return cast<UsingShadowDecl>(this)->getTargetDecl() ==
- cast<UsingShadowDecl>(OldD)->getTargetDecl();
+ // For function templates, the underlying function declarations are linked.
+ if (const FunctionTemplateDecl *FunctionTemplate =
+ dyn_cast<FunctionTemplateDecl>(this))
+ return FunctionTemplate->getTemplatedDecl()->declarationReplaces(
+ cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl());
+
+ // Using shadow declarations can be overloaded on their target declarations
+ // if they introduce functions.
+ // FIXME: If our target replaces the old target, can we replace the old
+ // shadow declaration?
+ if (auto *USD = dyn_cast<UsingShadowDecl>(this))
+ if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl())
+ return false;
- if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) {
+ // Using declarations can be overloaded if they introduce functions.
+ if (auto *UD = dyn_cast<UsingDecl>(this)) {
ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(this)->getQualifier()) ==
+ return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(OldD)->getQualifier());
+ cast<UsingDecl>(OldD)->getQualifier());
}
-
- if (isa<UnresolvedUsingValueDecl>(this) &&
- isa<UnresolvedUsingValueDecl>(OldD)) {
+ if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(
- cast<UnresolvedUsingValueDecl>(this)->getQualifier()) ==
+ return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
Context.getCanonicalNestedNameSpecifier(
cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
}
- // A typedef of an Objective-C class type can replace an Objective-C class
- // declaration or definition, and vice versa.
- // FIXME: Is this correct if one of the decls comes from an inline namespace?
- if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
- (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD)))
- return true;
+ // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
+ // We want to keep it, unless it nominates same namespace.
+ if (auto *UD = dyn_cast<UsingDirectiveDecl>(this))
+ return UD->getNominatedNamespace()->getOriginalNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
+ ->getOriginalNamespace();
+
+ if (!IsKnownNewer && isRedeclarable(getKind())) {
+ // Check whether this is actually newer than OldD. We want to keep the
+ // newer declaration. This loop will usually only iterate once, because
+ // OldD is usually the previous declaration.
+ for (auto D : redecls()) {
+ if (D == OldD)
+ break;
+
+ // If we reach the canonical declaration, then OldD is not actually older
+ // than this one.
+ //
+ // FIXME: In this case, we should not add this decl to the lookup table.
+ if (D->isCanonicalDecl())
+ return false;
+ }
+ }
- // For non-function declarations, if the declarations are of the
- // same kind and have the same parent then this must be a redeclaration,
- // or semantic analysis would not have given us the new declaration.
- // Note that inline namespaces can give us two declarations with the same
- // name and kind in the same scope but different contexts.
- return this->getKind() == OldD->getKind() &&
- this->getDeclContext()->getRedeclContext()->Equals(
- OldD->getDeclContext()->getRedeclContext());
+ // It's a newer declaration of the same kind of declaration in the same scope,
+ // and not an overload: we want this decl instead of the existing one.
+ return true;
}
bool NamedDecl::hasLinkage() const {
@@ -1684,8 +1743,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
if (NumTPLists > 0) {
TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
NumTemplParamLists = NumTPLists;
- for (unsigned i = NumTPLists; i-- > 0; )
- TemplParamLists[i] = TPLists[i];
+ std::copy(TPLists, TPLists + NumTPLists, TemplParamLists);
}
}
@@ -1717,6 +1775,8 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
"VarDeclBitfields too large!");
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
"ParmVarDeclBitfields too large!");
+ static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
+ "NonParmVarDeclBitfields too large!");
AllBits = 0;
VarDeclBits.SClass = SC;
// Everything else is implicitly initialized to false.
@@ -1743,12 +1803,19 @@ void VarDecl::setStorageClass(StorageClass SC) {
VarDecl::TLSKind VarDecl::getTLSKind() const {
switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
- if (hasAttr<ThreadAttr>())
- return TLS_Static;
- return TLS_None;
+ if (!hasAttr<ThreadAttr>() &&
+ !(getASTContext().getLangOpts().OpenMPUseTLS &&
+ getASTContext().getTargetInfo().isTLSSupported() &&
+ hasAttr<OMPThreadPrivateDeclAttr>()))
+ return TLS_None;
+ 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;
}
@@ -1825,9 +1892,8 @@ bool VarDecl::isInExternCXXContext() const {
VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
-VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
- ASTContext &C) const
-{
+VarDecl::DefinitionKind
+VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
@@ -1867,6 +1933,10 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
if (hasAttr<AliasAttr>())
return Definition;
+ if (const auto *SAA = getAttr<SelectAnyAttr>())
+ if (!SAA->isInherited())
+ return Definition;
+
// A variable template specialization (other than a static data member
// template or an explicit specialization) is a declaration until we
// instantiate its initializer.
@@ -2460,39 +2530,6 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
}
-FunctionDecl *
-FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const {
- ASTContext &Ctx = getASTContext();
- if (!Ctx.getLangOpts().SizedDeallocation)
- return nullptr;
-
- if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
- return nullptr;
- if (getDeclName().getCXXOverloadedOperator() != OO_Delete &&
- getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
- return nullptr;
- if (isa<CXXRecordDecl>(getDeclContext()))
- return nullptr;
-
- if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
- return nullptr;
-
- if (getNumParams() != 2 || isVariadic() ||
- !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1),
- Ctx.getSizeType()))
- return nullptr;
-
- // This is a sized deallocation function. Find the corresponding unsized
- // deallocation function.
- lookup_const_result R = getDeclContext()->lookup(getDeclName());
- for (lookup_const_result::iterator RI = R.begin(), RE = R.end(); RI != RE;
- ++RI)
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI))
- if (FD->getNumParams() == 1 && !FD->isVariadic())
- return FD;
- return nullptr;
-}
-
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
@@ -2550,10 +2587,6 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
IsInline = true;
}
-const FunctionDecl *FunctionDecl::getCanonicalDecl() const {
- return getFirstDecl();
-}
-
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
/// \brief Returns a value indicating whether this function
@@ -2581,7 +2614,14 @@ unsigned FunctionDecl::getBuiltinID() const {
// extern "C".
// FIXME: A recognised library function may not be directly in an extern "C"
// declaration, for instance "extern "C" { namespace std { decl } }".
- if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
+ if (!LinkageDecl) {
+ if (BuiltinID == Builtin::BI__GetExceptionInfo &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ isInStdNamespace())
+ return Builtin::BI__GetExceptionInfo;
+ return 0;
+ }
+ if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
return 0;
}
@@ -2676,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;
@@ -2688,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;
@@ -2796,6 +2836,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const {
return RTRange;
}
+bool FunctionDecl::hasUnusedResultAttr() const {
+ QualType RetType = getReturnType();
+ if (RetType->isRecordType()) {
+ const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
+ if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
+ !(MD && MD->getCorrespondingMethodInClass(Ret, true)))
+ return true;
+ }
+ return hasAttr<WarnUnusedResultAttr>();
+}
+
/// \brief For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
@@ -3077,6 +3129,8 @@ DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
+ static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
d.NumTemplates = Ts.size();
d.NumArgs = TArgs.size();
@@ -3590,7 +3644,7 @@ void RecordDecl::completeDefinition() {
/// This which can be turned on with an attribute, pragma, or the
/// -mms-bitfields command-line option.
bool RecordDecl::isMsStruct(const ASTContext &C) const {
- return hasAttr<MsStructAttr>() || C.getLangOpts().MSBitfields == 1;
+ return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
}
static bool isFieldOrIndirectField(Decl::Kind K) {
@@ -3631,7 +3685,8 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) ||
+ if (!Context.getLangOpts().Sanitize.hasOneOf(
+ SanitizerKind::Address | SanitizerKind::KernelAddress) ||
!Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
const auto &Blacklist = Context.getSanitizerBlacklist();
@@ -3747,6 +3802,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}
+void ExternCContextDecl::anchor() { }
+
+ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
+ TranslationUnitDecl *DC) {
+ return new (C, DC) ExternCContextDecl(DC);
+}
+
void LabelDecl::anchor() { }
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3885,6 +3947,21 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
void TypedefNameDecl::anchor() { }
+TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
+ if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
+ auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
+ auto *ThisTypedef = this;
+ if (AnyRedecl && OwningTypedef) {
+ OwningTypedef = OwningTypedef->getCanonicalDecl();
+ ThisTypedef = ThisTypedef->getCanonicalDecl();
+ }
+ if (OwningTypedef == ThisTypedef)
+ return TT->getDecl();
+ }
+
+ return nullptr;
+}
+
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index a46787f..4fcec53 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -66,6 +66,12 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
DeclContext *Parent, std::size_t Extra) {
assert(!Parent || &Parent->getParentASTContext() == &Ctx);
+ // With local visibility enabled, we track the owning module even for local
+ // declarations.
+ if (Ctx.getLangOpts().ModulesLocalVisibility) {
+ void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx);
+ return new (Buffer) Module*(nullptr) + 1;
+ }
return ::operator new(Size + Extra, Ctx);
}
@@ -74,6 +80,10 @@ Module *Decl::getOwningModuleSlow() const {
return getASTContext().getExternalSource()->getModule(getOwningModuleID());
}
+bool Decl::hasLocalOwningModuleStorage() const {
+ return getASTContext().getLangOpts().ModulesLocalVisibility;
+}
+
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: llvm_unreachable("Declaration not in DeclNodes.inc!");
@@ -226,6 +236,7 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
} else {
getMultipleDC()->LexicalDC = DC;
}
+ Hidden = cast<Decl>(DC)->Hidden;
}
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
@@ -336,20 +347,34 @@ bool Decl::isReferenced() const {
static AvailabilityResult CheckAvailability(ASTContext &Context,
const AvailabilityAttr *A,
std::string *Message) {
- StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
- StringRef PrettyPlatformName
- = AvailabilityAttr::getPrettyPlatformName(TargetPlatform);
- if (PrettyPlatformName.empty())
- PrettyPlatformName = TargetPlatform;
+ VersionTuple TargetMinVersion =
+ Context.getTargetInfo().getPlatformMinVersion();
- VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion();
if (TargetMinVersion.empty())
return AR_Available;
+ // Check if this is an App Extension "platform", and if so chop off
+ // the suffix for matching with the actual platform.
+ StringRef ActualPlatform = A->getPlatform()->getName();
+ StringRef RealizedPlatform = ActualPlatform;
+ if (Context.getLangOpts().AppExt) {
+ size_t suffix = RealizedPlatform.rfind("_app_extension");
+ if (suffix != StringRef::npos)
+ RealizedPlatform = RealizedPlatform.slice(0, suffix);
+ }
+
+ StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
+
// Match the platform name.
- if (A->getPlatform()->getName() != TargetPlatform)
+ if (RealizedPlatform != TargetPlatform)
return AR_Available;
-
+
+ StringRef PrettyPlatformName
+ = AvailabilityAttr::getPrettyPlatformName(ActualPlatform);
+
+ if (PrettyPlatformName.empty())
+ PrettyPlatformName = ActualPlatform;
+
std::string HintMessage;
if (!A->getMessage().empty()) {
HintMessage = " - ";
@@ -536,6 +561,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case TypeAliasTemplate:
case UnresolvedUsingTypename:
case TemplateTypeParm:
+ case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
case UsingShadow:
@@ -583,6 +609,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Block:
case Captured:
case TranslationUnit:
+ case ExternCContext:
case UsingDirective:
case ClassTemplateSpecialization:
@@ -846,6 +873,10 @@ bool DeclContext::isDependentContext() const {
return getLexicalParent()->isDependentContext();
}
+ // FIXME: A variable template is a dependent context, but is not a
+ // DeclContext. A context within it (such as a lambda-expression)
+ // should be considered dependent.
+
return getParent() && getParent()->isDependentContext();
}
@@ -889,6 +920,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
DeclContext *DeclContext::getPrimaryContext() {
switch (DeclKind) {
case Decl::TranslationUnit:
+ case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Block:
case Decl::Captured:
@@ -991,23 +1023,24 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() const {
- assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer());
+ assert(NeedToReconcileExternalVisibleStorage && LookupPtr);
NeedToReconcileExternalVisibleStorage = false;
- for (auto &Lookup : *LookupPtr.getPointer())
+ for (auto &Lookup : *LookupPtr)
Lookup.second.setHasExternalDecls();
}
/// \brief Load the declarations within this lexical storage from an
/// external source.
-void
+/// \return \c true if any declarations were added.
+bool
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
-
+
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
ExternalLexicalStorage = false;
@@ -1017,11 +1050,11 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
case ELR_Failure:
case ELR_AlreadyLoaded:
- return;
+ return false;
}
if (Decls.empty())
- return;
+ return false;
// We may have already loaded just the fields of this record, in which case
// we need to ignore them.
@@ -1038,6 +1071,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
FirstDecl = ExternalFirst;
if (!LastDecl)
LastDecl = ExternalLast;
+ return true;
}
DeclContext::lookup_result
@@ -1045,7 +1079,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1061,7 +1095,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
ArrayRef<NamedDecl*> Decls) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1078,7 +1112,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
// first.
llvm::SmallVector<unsigned, 8> Skip;
for (unsigned I = 0, N = Decls.size(); I != N; ++I)
- if (List.HandleRedeclaration(Decls[I]))
+ if (List.HandleRedeclaration(Decls[I], /*IsKnownNewer*/false))
Skip.push_back(I);
Skip.push_back(Decls.size());
@@ -1155,7 +1189,7 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
- StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer();
+ StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
if (!Map) return;
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
@@ -1243,32 +1277,38 @@ static bool shouldBeHidden(NamedDecl *D) {
StoredDeclsMap *DeclContext::buildLookup() {
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
- // FIXME: Should we keep going if hasExternalVisibleStorage?
- if (!LookupPtr.getInt())
- return LookupPtr.getPointer();
+ if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups)
+ return LookupPtr;
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
- for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::decls_begin,
- &DeclContext::decls_end>(Contexts[I]);
+
+ if (HasLazyExternalLexicalLookups) {
+ HasLazyExternalLexicalLookups = false;
+ for (auto *DC : Contexts) {
+ if (DC->hasExternalLexicalStorage())
+ HasLazyLocalLexicalLookups |=
+ DC->LoadLexicalDeclsFromExternalStorage();
+ }
+
+ if (!HasLazyLocalLexicalLookups)
+ return LookupPtr;
+ }
+
+ for (auto *DC : Contexts)
+ buildLookupImpl(DC, hasExternalVisibleStorage());
// We no longer have any lazy decls.
- LookupPtr.setInt(false);
- return LookupPtr.getPointer();
+ HasLazyLocalLexicalLookups = false;
+ return LookupPtr;
}
/// buildLookupImpl - Build part of the lookup data structure for the
/// declarations contained within DCtx, which will either be this
/// DeclContext, a DeclContext linked to it, or a transparent context
/// nested within it.
-template<DeclContext::decl_iterator (DeclContext::*Begin)() const,
- DeclContext::decl_iterator (DeclContext::*End)() const>
-void DeclContext::buildLookupImpl(DeclContext *DCtx) {
- for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)();
- I != E; ++I) {
- Decl *D = *I;
-
+void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
+ for (Decl *D : DCtx->noload_decls()) {
// Insert this declaration into the lookup structure, but only if
// it's semantically within its decl context. Any other decls which
// should be found in this context are added eagerly.
@@ -1282,39 +1322,46 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) {
(!ND->isFromASTFile() ||
(isTranslationUnit() &&
!getParentASTContext().getLangOpts().CPlusPlus)))
- makeDeclVisibleInContextImpl(ND, false);
+ makeDeclVisibleInContextImpl(ND, Internal);
// If this declaration is itself a transparent declaration context
// or inline namespace, add the members of this declaration of that
// context (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))
if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
- buildLookupImpl<Begin, End>(InnerCtx);
+ buildLookupImpl(InnerCtx, Internal);
}
}
+NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
+
DeclContext::lookup_result
-DeclContext::lookup(DeclarationName Name) {
+DeclContext::lookup(DeclarationName Name) const {
assert(DeclKind != Decl::LinkageSpec &&
"Should not perform lookups into linkage specs!");
- DeclContext *PrimaryContext = getPrimaryContext();
+ const DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
- // If this is a namespace, ensure that any later redeclarations of it have
- // been loaded, since they may add names to the result of this lookup.
- if (auto *ND = dyn_cast<NamespaceDecl>(this))
- (void)ND->getMostRecentDecl();
+ // If we have an external source, ensure that any later redeclarations of this
+ // context have been loaded, since they may add names to the result of this
+ // lookup (or add external visible storage).
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ if (Source)
+ (void)cast<Decl>(this)->getMostRecentDecl();
if (hasExternalVisibleStorage()) {
+ assert(Source && "external visible storage but no external source?");
+
if (NeedToReconcileExternalVisibleStorage)
reconcileExternalVisibleStorage();
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
- if (LookupPtr.getInt())
- Map = buildLookup();
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ // FIXME: Make buildLookup const?
+ Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
Map = CreateStoredDeclsMap(getParentASTContext());
@@ -1325,28 +1372,27 @@ DeclContext::lookup(DeclarationName Name) {
if (!R.second && !R.first->second.hasExternalDecls())
return R.first->second.getLookupResult();
- ExternalASTSource *Source = getParentASTContext().getExternalSource();
if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator I = Map->find(Name);
if (I != Map->end())
return I->second.getLookupResult();
}
}
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
}
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt())
- Map = buildLookup();
+ StoredDeclsMap *Map = LookupPtr;
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
StoredDeclsMap::iterator I = Map->find(Name);
if (I == Map->end())
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
return I->second.getLookupResult();
}
@@ -1355,40 +1401,29 @@ DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
assert(DeclKind != Decl::LinkageSpec &&
"Should not perform lookups into linkage specs!");
- if (!hasExternalVisibleStorage())
- return lookup(Name);
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->noload_lookup(Name);
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt()) {
- // Carefully build the lookup map, without deserializing anything.
+ // If we have any lazy lexical declarations not in our lookup map, add them
+ // now. Don't import any external declarations, not even if we know we have
+ // some missing from the external visible lookups.
+ if (HasLazyLocalLexicalLookups) {
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::noload_decls_begin,
- &DeclContext::noload_decls_end>(Contexts[I]);
-
- // We no longer have any lazy decls.
- LookupPtr.setInt(false);
-
- // There may now be names for which we have local decls but are
- // missing the external decls. FIXME: Just set the hasExternalDecls
- // flag on those names that have external decls.
- NeedToReconcileExternalVisibleStorage = true;
-
- Map = LookupPtr.getPointer();
+ buildLookupImpl(Contexts[I], hasExternalVisibleStorage());
+ HasLazyLocalLexicalLookups = false;
}
+ StoredDeclsMap *Map = LookupPtr;
if (!Map)
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
StoredDeclsMap::iterator I = Map->find(Name);
return I != Map->end() ? I->second.getLookupResult()
- : lookup_result(lookup_iterator(nullptr),
- lookup_iterator(nullptr));
+ : lookup_result();
}
void DeclContext::localUncachedLookup(DeclarationName Name,
@@ -1404,8 +1439,9 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
}
// If we have a lookup table, check there first. Maybe we'll get lucky.
- if (Name && !LookupPtr.getInt()) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ // FIXME: Should we be checking these flags on the primary context?
+ if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos != Map->end()) {
Results.insert(Results.end(),
@@ -1418,6 +1454,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
// Slow case: grovel through the declarations in our chain looking for
// matches.
+ // FIXME: If we have lazy external declarations, this will not find them!
+ // FIXME: Should we CollectAllContexts and walk them all here?
for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->getDeclName() == Name)
@@ -1498,7 +1536,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
// FIXME: As a performance hack, don't add such decls into the translation
// unit unless we're in C++, since qualified lookup into the TU is never
// performed.
- if (LookupPtr.getPointer() || hasExternalVisibleStorage() ||
+ if (LookupPtr || hasExternalVisibleStorage() ||
((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) &&
(getParentASTContext().getLangOpts().CPlusPlus ||
!isTranslationUnit()))) {
@@ -1508,7 +1546,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
buildLookup();
makeDeclVisibleInContextImpl(D, Internal);
} else {
- LookupPtr.setInt(true);
+ HasLazyLocalLexicalLookups = true;
}
// If we are a transparent context or inline namespace, insert into our
@@ -1526,7 +1564,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
// Find or create the stored declaration map.
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
if (!Map) {
ASTContext *C = &getParentASTContext();
Map = CreateStoredDeclsMap(*C);
@@ -1555,12 +1593,12 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
return;
}
- else if (DeclNameEntries.isNull()) {
+ if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
}
- if (DeclNameEntries.HandleRedeclaration(D)) {
+ if (DeclNameEntries.HandleRedeclaration(D, /*IsKnownNewer*/!Internal)) {
// This declaration has replaced an existing one for which
// declarationReplaces returns true.
return;
@@ -1570,15 +1608,17 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
DeclNameEntries.AddSubsequentDecl(D);
}
+UsingDirectiveDecl *DeclContext::udir_iterator::operator*() const {
+ return cast<UsingDirectiveDecl>(*I);
+}
+
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_range DeclContext::using_directives() const {
// FIXME: Use something more efficient than normal lookup for using
// directives. In C++, using directives are looked up more than anything else.
- lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
- return udir_range(
- reinterpret_cast<UsingDirectiveDecl *const *>(Result.begin()),
- reinterpret_cast<UsingDirectiveDecl *const *>(Result.end()));
+ lookup_result Result = lookup(UsingDirectiveDecl::getName());
+ return udir_range(Result.begin(), Result.end());
}
//===----------------------------------------------------------------------===//
@@ -1586,7 +1626,7 @@ DeclContext::udir_range DeclContext::using_directives() const {
//===----------------------------------------------------------------------===//
StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
- assert(!LookupPtr.getPointer() && "context already has a decls map");
+ assert(!LookupPtr && "context already has a decls map");
assert(getPrimaryContext() == this &&
"creating decls map on non-primary context");
@@ -1598,7 +1638,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
M = new StoredDeclsMap();
M->Previous = C.LastSDM;
C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
- LookupPtr.setPointer(M);
+ LookupPtr = M;
return M;
}
@@ -1630,11 +1670,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
assert(Parent->isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
Parent = Parent->getPrimaryContext();
- if (!Parent->LookupPtr.getPointer())
+ if (!Parent->LookupPtr)
Parent->CreateStoredDeclsMap(C);
- DependentStoredDeclsMap *Map
- = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer());
+ DependentStoredDeclsMap *Map =
+ static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index 9af8c4b..d905fcf 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -991,7 +991,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
- DeclContext::lookup_const_result Calls = lookup(Name);
+ DeclContext::lookup_result Calls = lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
assert(Calls.size() == 1 && "More than one lambda call operator!");
@@ -1008,7 +1008,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
&getASTContext().Idents.get(getLambdaStaticInvokerName());
- DeclContext::lookup_const_result Invoker = lookup(Name);
+ DeclContext::lookup_result Invoker = lookup(Name);
if (Invoker.empty()) return nullptr;
assert(Invoker.size() == 1 && "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
@@ -1173,7 +1173,7 @@ static void CollectVisibleConversions(ASTContext &Context,
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
-std::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator>
+llvm::iterator_range<CXXRecordDecl::conversion_iterator>
CXXRecordDecl::getVisibleConversionFunctions() {
ASTContext &Ctx = getASTContext();
@@ -1189,7 +1189,7 @@ CXXRecordDecl::getVisibleConversionFunctions() {
data().ComputedVisibleConversions = true;
}
}
- return std::make_pair(Set->begin(), Set->end());
+ return llvm::make_range(Set->begin(), Set->end());
}
void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
@@ -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();
}
}
@@ -1307,7 +1307,7 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
= Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(ClassType));
- DeclContext::lookup_const_result R = lookup(Name);
+ DeclContext::lookup_result R = lookup(Name);
if (R.empty())
return nullptr;
@@ -1315,6 +1315,28 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
return Dtor;
}
+bool CXXRecordDecl::isAnyDestructorNoReturn() const {
+ // Destructor is noreturn.
+ if (const CXXDestructorDecl *Destructor = getDestructor())
+ if (Destructor->isNoReturn())
+ return true;
+
+ // Check base classes destructor for noreturn.
+ for (const auto &Base : bases())
+ if (Base.getType()->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
+ return true;
+
+ // Check fields for noreturn.
+ for (const auto *Field : fields())
+ if (const CXXRecordDecl *RD =
+ Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
+ if (RD->isAnyDestructorNoReturn())
+ return true;
+
+ // All destructors are not noreturn.
+ return false;
+}
+
void CXXRecordDecl::completeDefinition() {
completeDefinition(nullptr);
}
@@ -1418,9 +1440,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
return nullptr;
}
- lookup_const_result Candidates = RD->lookup(getDeclName());
- for (NamedDecl * const * I = Candidates.begin(); I != Candidates.end(); ++I) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I);
+ for (auto *ND : RD->lookup(getDeclName())) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND);
if (!MD)
continue;
if (recursivelyOverrides(MD, this))
@@ -1491,8 +1512,8 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
- DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName());
- for (DeclContext::lookup_const_result::iterator I = R.begin(), E = R.end();
+ DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
+ for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
I != E; ++I) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
if (FD->getNumParams() == 1)
@@ -1740,6 +1761,10 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isImplicitlyDeclared, isConstexpr);
}
+CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
+ return CtorInitializers.get(getASTContext().getExternalSource());
+}
+
CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
assert(isDelegatingConstructor() && "Not a delegating constructor!");
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
@@ -1887,6 +1912,15 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isInline, isImplicitlyDeclared);
}
+void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) {
+ auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+ if (OD && !First->OperatorDelete) {
+ First->OperatorDelete = OD;
+ if (auto *L = getASTMutationListener())
+ L->ResolvedOperatorDelete(First, OD);
+ }
+}
+
void CXXConversionDecl::anchor() { }
CXXConversionDecl *
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
index 9861f22..512837f 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
@@ -18,6 +18,8 @@
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
assert(NumDecls > 1 && "Invalid DeclGroup");
unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index ed53675..280c412 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -54,8 +54,8 @@ void ObjCContainerDecl::anchor() { }
///
ObjCIvarDecl *
ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
- lookup_const_result R = lookup(Id);
- for (lookup_const_iterator Ivar = R.begin(), IvarEnd = R.end();
+ lookup_result R = lookup(Id);
+ for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
Ivar != IvarEnd; ++Ivar) {
if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
return ivar;
@@ -83,8 +83,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
// + (float) class_method;
// @end
//
- lookup_const_result R = lookup(Sel);
- for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
+ lookup_result R = lookup(Sel);
+ for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() == isInstance)
@@ -101,8 +101,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
const ObjCPropertyDecl *Property) const {
Selector Sel = Property->getSetterName();
- lookup_const_result R = lookup(Sel);
- for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
+ lookup_result R = lookup(Sel);
+ for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() && !MD->isImplicit())
@@ -161,8 +161,8 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
return nullptr;
}
- DeclContext::lookup_const_result R = DC->lookup(propertyID);
- for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E;
+ DeclContext::lookup_result R = DC->lookup(propertyID);
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I)
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
return PD;
@@ -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.
@@ -334,9 +390,8 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
return;
// Merge ProtocolRefs into class's protocol list;
- for (auto *P : all_referenced_protocols()) {
- ProtocolRefs.push_back(P);
- }
+ ProtocolRefs.append(all_referenced_protocol_begin(),
+ all_referenced_protocol_end());
data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
}
@@ -617,8 +672,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
// Look through local category implementations associated with the class.
if (!Method)
- Method = Instance ? getCategoryInstanceMethod(Sel)
- : getCategoryClassMethod(Sel);
+ Method = getCategoryMethod(Sel, Instance);
// Before we give up, check if the selector is an instance method.
// But only in the root. This matches gcc's behavior and what the
@@ -891,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.
@@ -906,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>();
@@ -932,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);
@@ -968,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,
@@ -1101,7 +1177,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
if (NumArgs > 1)
return nullptr;
- if (!isInstanceMethod() || getMethodFamily() != OMF_None)
+ if (!isInstanceMethod())
return nullptr;
if (isPropertyAccessor()) {
@@ -1139,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
//===----------------------------------------------------------------------===//
@@ -1146,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;
@@ -1161,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);
@@ -1169,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.
@@ -1181,6 +1337,8 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
Data = PrevDecl->Data;
setImplicit(IsInternal);
+
+ setTypeParamList(typeParamList);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
@@ -1494,6 +1652,11 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
}
}
+QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
+ return getType().substObjCMemberType(objectType, getDeclContext(),
+ ObjCSubstitutionContext::Property);
+}
+
//===----------------------------------------------------------------------===//
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
@@ -1650,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();
@@ -1678,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 {
@@ -1690,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
@@ -1822,6 +2011,11 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
}
}
+ObjCImplementationDecl::init_const_iterator
+ObjCImplementationDecl::init_begin() const {
+ return IvarInitializers.get(getASTContext().getExternalSource());
+}
+
raw_ostream &clang::operator<<(raw_ostream &OS,
const ObjCImplementationDecl &ID) {
OS << ID.getName();
@@ -1859,16 +2053,23 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
SourceLocation AtLoc,
SourceLocation LParenLoc,
- TypeSourceInfo *T,
+ QualType T,
+ TypeSourceInfo *TSI,
PropertyControl propControl) {
- return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T);
+ return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,
+ propControl);
}
ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
SourceLocation(), SourceLocation(),
- nullptr);
+ QualType(), nullptr, None);
+}
+
+QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
+ return DeclType.substObjCMemberType(objectType, getDeclContext(),
+ ObjCSubstitutionContext::Property);
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index c0f3e17..3202d8c 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -37,6 +37,15 @@ namespace {
void Print(AccessSpecifier AS);
+ /// Print an Objective-C method type in parentheses.
+ ///
+ /// \param Quals The Objective-C declaration qualifiers.
+ /// \param T The type to print.
+ 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)
@@ -733,8 +742,10 @@ void DeclPrinter::VisitImportDecl(ImportDecl *D) {
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
Out << "static_assert(";
D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
- Out << ", ";
- D->getMessage()->printPretty(Out, nullptr, Policy, Indentation);
+ if (StringLiteral *SL = D->getMessage()) {
+ Out << ", ";
+ SL->printPretty(Out, nullptr, Policy, Indentation);
+ }
Out << ")";
}
@@ -928,24 +939,83 @@ void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Objective-C declarations
//----------------------------------------------------------------------------
+void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
+ Decl::ObjCDeclQualifier Quals,
+ QualType T) {
+ Out << '(';
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
+ Out << "in ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
+ Out << "inout ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
+ Out << "out ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
+ Out << "bycopy ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
+ Out << "byref ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
+ Out << "oneway ";
+ if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
+ if (auto nullability = AttributedType::stripOuterNullability(T))
+ Out << getNullabilitySpelling(*nullability, true) << ' ';
+ }
+
+ Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
+ 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 << "- ";
else
Out << "+ ";
- if (!OMD->getReturnType().isNull())
- Out << '(' << OMD->getASTContext()
- .getUnqualifiedObjCPointerType(OMD->getReturnType())
- .getAsString(Policy) << ")";
+ if (!OMD->getReturnType().isNull()) {
+ PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),
+ OMD->getReturnType());
+ }
std::string name = OMD->getSelector().getAsString();
std::string::size_type pos, lastPos = 0;
for (const auto *PI : OMD->params()) {
// FIXME: selector is missing here!
pos = name.find_first_of(':', lastPos);
- Out << " " << name.substr(lastPos, pos - lastPos);
- Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).
- getAsString(Policy) << ')' << *PI;
+ Out << " " << name.substr(lastPos, pos - lastPos) << ':';
+ PrintObjCMethodType(OMD->getASTContext(),
+ PI->getObjCDeclQualifier(),
+ PI->getType());
+ Out << *PI;
lastPos = pos + 1;
}
@@ -1001,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();
@@ -1071,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;
@@ -1101,6 +1185,8 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
Out << "@optional\n";
+ QualType T = PDecl->getType();
+
Out << "@property";
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
bool first = true;
@@ -1159,10 +1245,25 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
first = false;
}
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_nullability) {
+ if (auto nullability = AttributedType::stripOuterNullability(T)) {
+ if (*nullability == NullabilityKind::Unspecified &&
+ (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_null_resettable)) {
+ Out << (first ? ' ' : ',') << "null_resettable";
+ } else {
+ Out << (first ? ' ' : ',')
+ << getNullabilitySpelling(*nullability, true);
+ }
+ first = false;
+ }
+ }
+
(void) first; // Silence dead store warning due to idiomatic code.
Out << " )";
}
- Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).
+ Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
getAsString(Policy) << ' ' << *PDecl;
if (Policy.PolishForDeclaration)
Out << ';';
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
index 0d1d2a4..cde497b 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -124,6 +124,12 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
}
}
+namespace clang {
+void *allocateDefaultArgStorageChain(const ASTContext &C) {
+ return new (C) char[sizeof(void*) * 2];
+}
+}
+
//===----------------------------------------------------------------------===//
// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -160,17 +166,43 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
return Common;
}
-template <class EntryType>
-typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+template<class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
RedeclarableTemplateDecl::findSpecializationImpl(
- llvm::FoldingSetVector<EntryType> &Specs,
- ArrayRef<TemplateArgument> Args,
- void *&InsertPos) {
+ llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args,
+ void *&InsertPos) {
typedef SpecEntryTraits<EntryType> SETraits;
llvm::FoldingSetNodeID ID;
EntryType::Profile(ID,Args, getASTContext());
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
- return Entry ? SETraits::getMostRecentDecl(Entry) : nullptr;
+ return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
+}
+
+template<class Derived, class EntryType>
+void RedeclarableTemplateDecl::addSpecializationImpl(
+ llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
+ void *InsertPos) {
+ typedef SpecEntryTraits<EntryType> SETraits;
+ if (InsertPos) {
+#ifndef NDEBUG
+ void *CorrectInsertPos;
+ assert(!findSpecializationImpl(Specializations,
+ SETraits::getTemplateArgs(Entry),
+ CorrectInsertPos) &&
+ InsertPos == CorrectInsertPos &&
+ "given incorrect InsertPos for specialization");
+#endif
+ Specializations.InsertNode(Entry, InsertPos);
+ } else {
+ EntryType *Existing = Specializations.GetOrInsertNode(Entry);
+ (void)Existing;
+ assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
+ "non-canonical specialization?");
+ }
+
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->AddedCXXTemplateSpecialization(cast<Derived>(this),
+ SETraits::getDecl(Entry));
}
/// \brief Generate the injected template arguments for the given template
@@ -246,7 +278,11 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const {
}
void FunctionTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -270,12 +306,8 @@ FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void FunctionTemplateDecl::addSpecialization(
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(Info, InsertPos);
- else
- getSpecializations().GetOrInsertNode(Info);
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, Info->Function);
+ addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
+ InsertPos);
}
ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
@@ -320,7 +352,11 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
}
void ClassTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -357,16 +393,7 @@ ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(D, InsertPos);
- else {
- ClassTemplateSpecializationDecl *Existing
- = getSpecializations().GetOrInsertNode(D);
- (void)Existing;
- assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
- }
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, D);
+ addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
}
ClassTemplatePartialSpecializationDecl *
@@ -483,14 +510,14 @@ TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
return hasDefaultArgument()
- ? DefaultArgument->getTypeLoc().getBeginLoc()
- : SourceLocation();
+ ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc()
+ : SourceLocation();
}
SourceRange TemplateTypeParmDecl::getSourceRange() const {
if (hasDefaultArgument() && !defaultArgumentWasInherited())
return SourceRange(getLocStart(),
- DefaultArgument->getTypeLoc().getEndLoc());
+ getDefaultArgumentInfo()->getTypeLoc().getEndLoc());
else
return TypeDecl::getSourceRange();
}
@@ -522,10 +549,8 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC,
unsigned NumExpandedTypes,
TypeSourceInfo **ExpandedTInfos)
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
- TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false),
- ParameterPack(true), ExpandedParameterPack(true),
- NumExpandedTypes(NumExpandedTypes)
-{
+ TemplateParmPosition(D, P), ParameterPack(true),
+ ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) {
if (ExpandedTypes && ExpandedTInfos) {
void **TypesAndInfos = reinterpret_cast<void **>(this + 1);
for (unsigned I = 0; I != NumExpandedTypes; ++I) {
@@ -600,8 +625,7 @@ TemplateTemplateParmDecl::TemplateTemplateParmDecl(
IdentifierInfo *Id, TemplateParameterList *Params,
unsigned NumExpansions, TemplateParameterList * const *Expansions)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
- TemplateParmPosition(D, P), DefaultArgument(),
- DefaultArgumentWasInherited(false), ParameterPack(true),
+ TemplateParmPosition(D, P), ParameterPack(true),
ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
if (Expansions)
std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
@@ -642,6 +666,19 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
nullptr, NumExpansions, nullptr);
}
+SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
+ return hasDefaultArgument() ? getDefaultArgument().getLocation()
+ : SourceLocation();
+}
+
+void TemplateTemplateParmDecl::setDefaultArgument(
+ const ASTContext &C, const TemplateArgumentLoc &DefArg) {
+ if (DefArg.getArgument().isNull())
+ DefaultArgument.set(nullptr);
+ else
+ DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
@@ -953,7 +990,11 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
// TODO: Unify across class, function and variable templates?
// May require moving this and Common to RedeclarableTemplateDecl.
void VarTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -990,16 +1031,7 @@ VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(D, InsertPos);
- else {
- VarTemplateSpecializationDecl *Existing =
- getSpecializations().GetOrInsertNode(D);
- (void)Existing;
- assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
- }
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, D);
+ addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos);
}
VarTemplatePartialSpecializationDecl *
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 712de50..2e066b2 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -1141,40 +1141,13 @@ CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn,
RParenLoc = rparenloc;
}
-CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args,
+CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
QualType t, ExprValueKind VK, SourceLocation rparenloc)
- : Expr(CallExprClass, t, VK, OK_Ordinary,
- fn->isTypeDependent(),
- fn->isValueDependent(),
- fn->isInstantiationDependent(),
- fn->containsUnexpandedParameterPack()),
- NumArgs(args.size()) {
-
- SubExprs = new (C) Stmt*[args.size()+PREARGS_START];
- SubExprs[FN] = fn;
- for (unsigned i = 0; i != args.size(); ++i) {
- if (args[i]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (args[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (args[i]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (args[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- SubExprs[i+PREARGS_START] = args[i];
- }
-
- CallExprBits.NumPreArgs = 0;
- RParenLoc = rparenloc;
+ : CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) {
}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
- // FIXME: Why do we allocate this?
- SubExprs = new (C) Stmt*[PREARGS_START];
- CallExprBits.NumPreArgs = 0;
-}
+ : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty)
@@ -1265,22 +1238,27 @@ unsigned CallExpr::getBuiltinCallee() const {
return FDecl->getBuiltinID();
}
-bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const {
+bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const {
if (unsigned BI = getBuiltinCallee())
return Ctx.BuiltinInfo.isUnevaluated(BI);
return false;
}
-QualType CallExpr::getCallReturnType() const {
- QualType CalleeType = getCallee()->getType();
- if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
+QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
+ const Expr *Callee = getCallee();
+ QualType CalleeType = Callee->getType();
+ if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) {
CalleeType = FnTypePtr->getPointeeType();
- else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
+ } else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) {
CalleeType = BPT->getPointeeType();
- else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember))
+ } else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
+ if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens()))
+ return Ctx.VoidTy;
+
// This should never be overloaded and so should never return null.
- CalleeType = Expr::findBoundMemberType(getCallee());
-
+ CalleeType = Expr::findBoundMemberType(Callee);
+ }
+
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
return FnType->getReturnType();
}
@@ -1360,16 +1338,50 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask);
}
-MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *memberdecl,
- DeclAccessPair founddecl,
- DeclarationNameInfo nameinfo,
- const TemplateArgumentListInfo *targs,
- QualType ty,
- ExprValueKind vk,
- ExprObjectKind ok) {
+UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType,
+ SourceLocation op, SourceLocation rp)
+ : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ E->isTypeDependent(), E->isInstantiationDependent(),
+ E->containsUnexpandedParameterPack()),
+ OpLoc(op), RParenLoc(rp) {
+ UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
+ UnaryExprOrTypeTraitExprBits.IsType = false;
+ Argument.Ex = E;
+
+ // Check to see if we are in the situation where alignof(decl) should be
+ // dependent because decl's alignment is dependent.
+ if (ExprKind == UETT_AlignOf) {
+ if (!isValueDependent() || !isInstantiationDependent()) {
+ E = E->IgnoreParens();
+
+ const ValueDecl *D = nullptr;
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ D = DRE->getDecl();
+ else if (const auto *ME = dyn_cast<MemberExpr>(E))
+ D = ME->getMemberDecl();
+
+ if (D) {
+ for (const auto *I : D->specific_attrs<AlignedAttr>()) {
+ if (I->isAlignmentDependent()) {
+ setValueDependent(true);
+ setInstantiationDependent(true);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+MemberExpr *MemberExpr::Create(
+ const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ValueDecl *memberdecl, DeclAccessPair founddecl,
+ DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs,
+ QualType ty, ExprValueKind vk, ExprObjectKind ok) {
std::size_t Size = sizeof(MemberExpr);
bool hasQualOrFound = (QualifierLoc ||
@@ -1384,8 +1396,8 @@ MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow,
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
- MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
- ty, vk, ok);
+ MemberExpr *E = new (Mem)
+ MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
if (hasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
@@ -2132,8 +2144,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
- if (Op->getCallReturnType()->isReferenceType() ||
- Op->getCallReturnType()->isVoidType())
+ if (Op->getCallReturnType(Ctx)->isReferenceType() ||
+ Op->getCallReturnType(Ctx)->isVoidType())
break;
WarnE = this;
Loc = Op->getOperatorLoc();
@@ -2149,12 +2161,16 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
+ bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
+ : FD->hasAttr<WarnUnusedResultAttr>();
+
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
// updated to match for QoI.
- if (FD->hasAttr<WarnUnusedResultAttr>() ||
+ if (HasWarnUnusedResultAttr ||
FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) {
WarnE = this;
Loc = CE->getCallee()->getLocStart();
@@ -2200,9 +2216,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
}
if (const ObjCMethodDecl *MD = ME->getMethodDecl())
- if (MD->hasAttr<WarnUnusedResultAttr>() ||
- (MD->isPropertyAccessor() && !MD->getReturnType()->isVoidType() &&
- !ME->getReceiverType()->isObjCIdType())) {
+ if (MD->hasAttr<WarnUnusedResultAttr>()) {
WarnE = this;
Loc = getExprLoc();
return true;
@@ -2387,7 +2401,7 @@ QualType Expr::findBoundMemberType(const Expr *expr) {
return type;
}
- assert(isa<UnresolvedMemberExpr>(expr));
+ assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr));
return QualType();
}
@@ -2758,6 +2772,11 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
return Exp->isConstantInitializer(Ctx, false, Culprit);
}
+ case DesignatedInitUpdateExprClass: {
+ const DesignatedInitUpdateExpr *DIUE = cast<DesignatedInitUpdateExpr>(this);
+ return DIUE->getBase()->isConstantInitializer(Ctx, false, Culprit) &&
+ DIUE->getUpdater()->isConstantInitializer(Ctx, false, Culprit);
+ }
case InitListExprClass: {
const InitListExpr *ILE = cast<InitListExpr>(this);
if (ILE->getType()->isArrayType()) {
@@ -2804,6 +2823,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
break;
}
case ImplicitValueInitExprClass:
+ case NoInitExprClass:
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()
@@ -2867,6 +2887,28 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
return false;
}
+namespace {
+ /// \brief Look for any side effects within a Stmt.
+ class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> {
+ typedef ConstEvaluatedExprVisitor<SideEffectFinder> Inherited;
+ const bool IncludePossibleEffects;
+ bool HasSideEffects;
+
+ public:
+ explicit SideEffectFinder(const ASTContext &Context, bool IncludePossible)
+ : Inherited(Context),
+ IncludePossibleEffects(IncludePossible), HasSideEffects(false) { }
+
+ bool hasSideEffects() const { return HasSideEffects; }
+
+ void VisitExpr(const Expr *E) {
+ if (!HasSideEffects &&
+ E->HasSideEffects(Context, IncludePossibleEffects))
+ HasSideEffects = true;
+ }
+ };
+}
+
bool Expr::HasSideEffects(const ASTContext &Ctx,
bool IncludePossibleEffects) const {
// In circumstances where we care about definite side effects instead of
@@ -2911,6 +2953,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case UnaryExprOrTypeTraitExprClass:
case AddrLabelExprClass:
case GNUNullExprClass:
+ case NoInitExprClass:
case CXXBoolLiteralExprClass:
case CXXNullPtrLiteralExprClass:
case CXXThisExprClass:
@@ -2932,11 +2975,19 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
case CUDAKernelCallExprClass:
+ case UserDefinedLiteralClass: {
+ // We don't know a call definitely has side effects, except for calls
+ // to pure/const functions that definitely don't.
+ // If the call itself is considered side-effect free, check the operands.
+ const Decl *FD = cast<CallExpr>(this)->getCalleeDecl();
+ bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>());
+ if (IsPure || !IncludePossibleEffects)
+ break;
+ return true;
+ }
+
case BlockExprClass:
case CXXBindTemporaryExprClass:
- case UserDefinedLiteralClass:
- // We don't know a call definitely has side effects, but we can check the
- // call's operands.
if (!IncludePossibleEffects)
break;
return true;
@@ -2945,7 +2996,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
- case StmtExprClass:
case CXXThrowExprClass:
case CXXNewExprClass:
case CXXDeleteExprClass:
@@ -2953,6 +3003,13 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
// These always have a side-effect.
return true;
+ case StmtExprClass: {
+ // StmtExprs have a side-effect if any substatement does.
+ SideEffectFinder Finder(Ctx, IncludePossibleEffects);
+ Finder.Visit(cast<StmtExpr>(this)->getSubStmt());
+ return Finder.hasSideEffects();
+ }
+
case ParenExprClass:
case ArraySubscriptExprClass:
case MemberExprClass:
@@ -2961,6 +3018,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CompoundLiteralExprClass:
case ExtVectorElementExprClass:
case DesignatedInitExprClass:
+ case DesignatedInitUpdateExprClass:
case ParenListExprClass:
case CXXPseudoDestructorExprClass:
case CXXStdInitializerListExprClass:
@@ -3096,31 +3154,31 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
}
// Recurse to children.
- for (const_child_range SubStmts = children(); SubStmts; ++SubStmts)
- if (const Stmt *S = *SubStmts)
- if (cast<Expr>(S)->HasSideEffects(Ctx, IncludePossibleEffects))
- return true;
+ for (const Stmt *SubStmt : children())
+ if (SubStmt &&
+ cast<Expr>(SubStmt)->HasSideEffects(Ctx, IncludePossibleEffects))
+ return true;
return false;
}
namespace {
/// \brief Look for a call to a non-trivial function within an expression.
- class NonTrivialCallFinder : public EvaluatedExprVisitor<NonTrivialCallFinder>
+ class NonTrivialCallFinder : public ConstEvaluatedExprVisitor<NonTrivialCallFinder>
{
- typedef EvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
-
+ typedef ConstEvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
+
bool NonTrivial;
public:
- explicit NonTrivialCallFinder(ASTContext &Context)
+ explicit NonTrivialCallFinder(const ASTContext &Context)
: Inherited(Context), NonTrivial(false) { }
bool hasNonTrivialCall() const { return NonTrivial; }
-
- void VisitCallExpr(CallExpr *E) {
- if (CXXMethodDecl *Method
- = dyn_cast_or_null<CXXMethodDecl>(E->getCalleeDecl())) {
+
+ void VisitCallExpr(const CallExpr *E) {
+ if (const CXXMethodDecl *Method
+ = dyn_cast_or_null<const CXXMethodDecl>(E->getCalleeDecl())) {
if (Method->isTrivial()) {
// Recurse to children of the call.
Inherited::VisitStmt(E);
@@ -3130,8 +3188,8 @@ namespace {
NonTrivial = true;
}
-
- void VisitCXXConstructExpr(CXXConstructExpr *E) {
+
+ void VisitCXXConstructExpr(const CXXConstructExpr *E) {
if (E->getConstructor()->isTrivial()) {
// Recurse to children of the call.
Inherited::VisitStmt(E);
@@ -3140,8 +3198,8 @@ namespace {
NonTrivial = true;
}
-
- void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+
+ void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) {
if (E->getTemporary()->getDestructor()->isTrivial()) {
Inherited::VisitStmt(E);
return;
@@ -3152,7 +3210,7 @@ namespace {
};
}
-bool Expr::hasNonTrivialCall(ASTContext &Ctx) {
+bool Expr::hasNonTrivialCall(const ASTContext &Ctx) const {
NonTrivialCallFinder Finder(Ctx);
Finder.Visit(this);
return Finder.hasNonTrivialCall();
@@ -3690,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:
@@ -3967,6 +4035,25 @@ void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx,
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
+DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
+ SourceLocation lBraceLoc, Expr *baseExpr, SourceLocation rBraceLoc)
+ : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
+ OK_Ordinary, false, false, false, false) {
+ BaseAndUpdaterExprs[0] = baseExpr;
+
+ InitListExpr *ILE = new (C) InitListExpr(C, lBraceLoc, None, rBraceLoc);
+ ILE->setType(baseExpr->getType());
+ BaseAndUpdaterExprs[1] = ILE;
+}
+
+SourceLocation DesignatedInitUpdateExpr::getLocStart() const {
+ return getBase()->getLocStart();
+}
+
+SourceLocation DesignatedInitUpdateExpr::getLocEnd() const {
+ return getBase()->getLocEnd();
+}
+
ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs,
SourceLocation rparenloc)
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index 9336166..d6f2ce6 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -208,8 +208,9 @@ void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
}
bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
- return getOperatorNew()->getType()->
- castAs<FunctionProtoType>()->isNothrow(Ctx);
+ return getOperatorNew()->getType()->castAs<FunctionProtoType>()->isNothrow(
+ Ctx) &&
+ !getOperatorNew()->isReservedGlobalPlacementOperator();
}
// CXXDeleteExpr
@@ -237,10 +238,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
SourceLocation ColonColonLoc, SourceLocation TildeLoc,
PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
- Context.getPointerType(Context.getFunctionType(
- Context.VoidTy, None,
- FunctionProtoType::ExtProtoInfo(
- Context.getDefaultCallingConvention(false, true)))),
+ Context.BoundMemberTy,
VK_RValue, OK_Ordinary,
/*isTypeDependent=*/(Base->isTypeDependent() ||
(DestroyedType.getTypeSourceInfo() &&
@@ -359,8 +357,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
Results = static_cast<DeclAccessPair *>(
C.Allocate(sizeof(DeclAccessPair) * NumResults,
llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, &*Begin.getIterator(),
- NumResults * sizeof(DeclAccessPair));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
// If we have explicit template arguments, check for dependent
@@ -401,8 +398,7 @@ void OverloadExpr::initializeResults(const ASTContext &C,
C.Allocate(sizeof(DeclAccessPair) * NumResults,
llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, &*Begin.getIterator(),
- NumResults * sizeof(DeclAccessPair));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
}
@@ -1031,6 +1027,11 @@ LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
}
+bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
+ return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
+ (getCallOperator() == C->getCapturedVar()->getDeclContext()));
+}
+
LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
return getLambdaClass()->getLambdaData().Captures;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
index 933ea97..9cc612e 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -183,6 +183,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::AtomicExprClass:
case Expr::CXXFoldExprClass:
+ case Expr::NoInitExprClass:
+ case Expr::DesignatedInitUpdateExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
@@ -283,7 +285,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXMemberCallExprClass:
case Expr::UserDefinedLiteralClass:
case Expr::CUDAKernelCallExprClass:
- return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
+ return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx));
// __builtin_choose_expr is equivalent to the chosen expression.
case Expr::ChooseExprClass:
@@ -418,9 +420,10 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
islvalue = NTTParm->getType()->isReferenceType();
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
- isa<IndirectFieldDecl>(D) ||
- (Ctx.getLangOpts().CPlusPlus &&
- (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)));
+ isa<IndirectFieldDecl>(D) ||
+ (Ctx.getLangOpts().CPlusPlus &&
+ (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
+ isa<FunctionTemplateDecl>(D)));
return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
}
@@ -605,7 +608,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
if (CT.isConstQualified())
return Cl::CM_ConstQualified;
if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant)
- return Cl::CM_ConstQualified;
+ return Cl::CM_ConstAddrSpace;
// Arrays are not modifiable, only their elements are.
if (CT->isArrayType())
@@ -671,6 +674,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
llvm_unreachable("CM_LValueCast and CL_LValue don't match");
case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
case Cl::CM_ConstQualified: return MLV_ConstQualified;
+ case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
case Cl::CM_ArrayType: return MLV_ArrayType;
case Cl::CM_IncompleteType: return MLV_IncompleteType;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 3d7f2dc..ed749cc 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -1406,7 +1406,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
return true;
}
-const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
+static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
return LVal.Base.dyn_cast<const ValueDecl*>();
}
@@ -2173,7 +2173,7 @@ struct CompleteObject {
assert(Value && "missing value for complete object");
}
- LLVM_EXPLICIT operator bool() const { return Value; }
+ explicit operator bool() const { return Value; }
};
/// Find the designated sub-object of an rvalue.
@@ -2502,8 +2502,9 @@ static bool AreElementsOfSameArray(QualType ObjType,
}
/// Find the complete object to which an LValue refers.
-CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
- const LValue &LVal, QualType LValType) {
+static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
+ AccessKinds AK, const LValue &LVal,
+ QualType LValType) {
if (!LVal.Base) {
Info.Diag(E, diag::note_constexpr_access_null) << AK;
return CompleteObject();
@@ -3726,8 +3727,9 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
// Skip this for non-union classes with no fields; in that case, the defaulted
// copy/move does not actually read the object.
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
- if (MD && MD->isDefaulted() && MD->isTrivial() &&
- (MD->getParent()->isUnion() || hasFields(MD->getParent()))) {
+ if (MD && MD->isDefaulted() &&
+ (MD->getParent()->isUnion() ||
+ (MD->isTrivial() && hasFields(MD->getParent())))) {
assert(This &&
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
LValue RHS;
@@ -3791,11 +3793,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
// Skip this for empty non-union classes; we should not perform an
// lvalue-to-rvalue conversion on them because their copy constructor does not
// actually read them.
- if (Definition->isDefaulted() &&
- ((Definition->isCopyConstructor() && Definition->isTrivial()) ||
- (Definition->isMoveConstructor() && Definition->isTrivial())) &&
+ if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() &&
(Definition->getParent()->isUnion() ||
- hasFields(Definition->getParent()))) {
+ (Definition->isTrivial() && hasFields(Definition->getParent())))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
@@ -4276,6 +4276,9 @@ public:
BlockScopeRAII Scope(Info);
const CompoundStmt *CS = E->getSubStmt();
+ if (CS->body_empty())
+ return true;
+
for (CompoundStmt::const_body_iterator BI = CS->body_begin(),
BE = CS->body_end();
/**/; ++BI) {
@@ -4301,6 +4304,8 @@ public:
return false;
}
}
+
+ llvm_unreachable("Return from function from the loop above.");
}
/// Visit a value which is evaluated, but whose value is ignored.
@@ -6834,7 +6839,7 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->isAssignmentOp())
+ if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
return Error(E);
if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
@@ -6846,7 +6851,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
ComplexValue LHS, RHS;
bool LHSOK;
- if (E->getLHS()->getType()->isRealFloatingType()) {
+ if (E->isAssignmentOp()) {
+ LValue LV;
+ EvaluateLValue(E->getLHS(), LV, Info);
+ LHSOK = false;
+ } else if (LHSTy->isRealFloatingType()) {
LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info);
if (LHSOK) {
LHS.makeComplexFloat();
@@ -7242,6 +7251,13 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
return Success(Sizeof, E);
}
+ case UETT_OpenMPRequiredSimdAlign:
+ assert(E->isArgumentType());
+ return Success(
+ Info.Ctx.toCharUnitsFromBits(
+ Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType()))
+ .getQuantity(),
+ E);
}
llvm_unreachable("unknown expr/type trait");
@@ -7586,10 +7602,23 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context,
else if (S->getString().getAsInteger(0, fill))
return false;
- if (SNaN)
- Result = llvm::APFloat::getSNaN(Sem, false, &fill);
- else
- Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ if (Context.getTargetInfo().isNan2008()) {
+ if (SNaN)
+ Result = llvm::APFloat::getSNaN(Sem, false, &fill);
+ else
+ Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ } else {
+ // Prior to IEEE 754-2008, architectures were allowed to choose whether
+ // the first bit of their significand was set for qNaN or sNaN. MIPS chose
+ // a different encoding to what became a standard in 2008, and for pre-
+ // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
+ // sNaN. This is now known as "legacy NaN" encoding.
+ if (SNaN)
+ Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ else
+ Result = llvm::APFloat::getSNaN(Sem, false, &fill);
+ }
+
return true;
}
@@ -8653,6 +8682,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::DesignatedInitExprClass:
+ case Expr::NoInitExprClass:
+ case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
case Expr::VAArgExprClass:
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
index 8894107..1c82c35 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
@@ -22,6 +22,16 @@ using namespace clang;
ExternalASTSource::~ExternalASTSource() { }
+llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
+ExternalASTSource::getSourceDescriptor(unsigned ID) {
+ return None;
+}
+
+ExternalASTSource::ASTSourceDescriptor
+ExternalASTSource::getSourceDescriptor(const Module &M) {
+ return ASTSourceDescriptor();
+}
+
void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls) {}
@@ -66,6 +76,11 @@ Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) {
return nullptr;
}
+CXXCtorInitializer **
+ExternalASTSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ return nullptr;
+}
+
CXXBaseSpecifier *
ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp
index eb3020c..0b82da1 100644
--- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp
@@ -22,11 +22,9 @@
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
+using namespace clang;
-using namespace llvm;
-
-namespace clang {
-
+namespace {
/// InheritanceHierarchyWriter - Helper class that writes out a
/// GraphViz file that diagrams the inheritance hierarchy starting at
/// a given C++ class type. Note that we do not use LLVM's
@@ -44,7 +42,8 @@ public:
: Context(Context), Out(Out) { }
void WriteGraph(QualType Type) {
- Out << "digraph \"" << DOT::EscapeString(Type.getAsString()) << "\" {\n";
+ Out << "digraph \"" << llvm::DOT::EscapeString(Type.getAsString())
+ << "\" {\n";
WriteNode(Type, false);
Out << "}\n";
}
@@ -59,6 +58,7 @@ protected:
/// (only) virtual base.
raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual);
};
+} // namespace
void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
QualType CanonType = Context.getCanonicalType(Type);
@@ -78,7 +78,7 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
// Give the node a label based on the name of the class.
std::string TypeName = Type.getAsString();
- Out << " [ shape=\"box\", label=\"" << DOT::EscapeString(TypeName);
+ Out << " [ shape=\"box\", label=\"" << llvm::DOT::EscapeString(TypeName);
// If the name of the class was a typedef or something different
// from the "real" class name, show the real class name in
@@ -139,9 +139,8 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
int FD;
SmallString<128> Filename;
- std::error_code EC =
- sys::fs::createTemporaryFile(Self.getAsString(), "dot", FD, Filename);
- if (EC) {
+ if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
+ Self.getAsString(), "dot", FD, Filename)) {
llvm::errs() << "Error: " << EC.message() << "\n";
return;
}
@@ -159,5 +158,3 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
// Display the graph
DisplayGraph(Filename);
}
-
-}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
index 378121c..7503cbf 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -106,7 +106,7 @@ public:
TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
uint64_t Width = Target.getTypeWidth(PtrDiff);
unsigned Align = Target.getTypeAlign(PtrDiff);
- if (MPT->getPointeeType()->isFunctionType())
+ if (MPT->isMemberFunctionPointer())
Width = 2 * Width;
return std::make_pair(Width, Align);
}
@@ -133,6 +133,22 @@ public:
return Layout.getNonVirtualSize() == PointerSize;
}
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return nullptr;
+ }
+
+ void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {}
+
+ void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) override {}
+
+ Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) override {
+ return nullptr;
+ }
+
MangleNumberingContext *createMangleNumberingContext() const override {
return new ItaniumNumberingContext();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index 156ad64..dac803e 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -42,8 +42,8 @@ using namespace clang;
namespace {
-/// \brief Retrieve the declaration context that should be used when mangling
-/// the given declaration.
+/// Retrieve the declaration context that should be used when mangling the given
+/// declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// The ABI assumes that lambda closure types that occur within
// default arguments live in the context of the function. However, due to
@@ -69,6 +69,14 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
return getEffectiveDeclContext(CD);
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (VD->isExternC())
+ return VD->getASTContext().getTranslationUnitDecl();
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isExternC())
+ return FD->getASTContext().getTranslationUnitDecl();
+
return DC;
}
@@ -156,12 +164,18 @@ public:
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
+ void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) override;
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
+ void mangleCXXVTableBitSet(const CXXRecordDecl *RD, raw_ostream &) override;
+
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -196,7 +210,7 @@ public:
/// @}
};
-/// CXXNameMangler - Manage the mangling of a single name.
+/// Manage the mangling of a single name.
class CXXNameMangler {
ItaniumMangleContextImpl &Context;
raw_ostream &Out;
@@ -207,7 +221,7 @@ class CXXNameMangler {
const NamedDecl *Structor;
unsigned StructorType;
- /// SeqID - The next subsitution sequence number.
+ /// The next substitution sequence number.
unsigned SeqID;
class FunctionTypeDepthState {
@@ -284,7 +298,7 @@ public:
#endif
raw_ostream &getStream() { return Out; }
- void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
+ void mangle(const NamedDecl *D);
void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
void mangleNumber(const llvm::APSInt &I);
void mangleNumber(int64_t Number);
@@ -317,10 +331,8 @@ private:
void addSubstitution(uintptr_t Ptr);
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned KnownArity = UnknownArity);
@@ -350,6 +362,9 @@ private:
void manglePrefix(QualType type);
void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
+ bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
+ StringRef Prefix = "");
+ void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleQualifiers(Qualifiers Quals);
void mangleRefQualifier(RefQualifierKind RefQualifier);
@@ -370,12 +385,14 @@ private:
void mangleAArch64NeonVectorType(const VectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
+ void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
+ void mangleInitListElements(const InitListExpr *InitList);
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
@@ -439,11 +456,11 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return true;
}
-void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
+void CXXNameMangler::mangle(const NamedDecl *D) {
// <mangled-name> ::= _Z <encoding>
// ::= <data name>
// ::= <special-name>
- Out << Prefix;
+ Out << "_Z";
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
mangleFunctionEncoding(FD);
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -519,7 +536,7 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
return DC;
}
-/// isStd - Return whether a given namespace is the 'std' namespace.
+/// Return whether a given namespace is the 'std' namespace.
static bool isStd(const NamespaceDecl *NS) {
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
->isTranslationUnit())
@@ -748,8 +765,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
}
void CXXNameMangler::manglePrefix(QualType type) {
- if (const TemplateSpecializationType *TST =
- type->getAs<TemplateSpecializationType>()) {
+ if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
@@ -759,17 +775,19 @@ void CXXNameMangler::manglePrefix(QualType type) {
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
- } else if (const DependentTemplateSpecializationType *DTST
- = type->getAs<DependentTemplateSpecializationType>()) {
- TemplateName Template
- = getASTContext().getDependentTemplateName(DTST->getQualifier(),
- DTST->getIdentifier());
- mangleTemplatePrefix(Template);
+ } else if (const auto *DTST =
+ type->getAs<DependentTemplateSpecializationType>()) {
+ if (!mangleSubstitution(QualType(DTST, 0))) {
+ TemplateName Template = getASTContext().getDependentTemplateName(
+ DTST->getQualifier(), DTST->getIdentifier());
+ mangleTemplatePrefix(Template);
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ addSubstitution(QualType(DTST, 0));
+ }
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
@@ -779,12 +797,9 @@ void CXXNameMangler::manglePrefix(QualType type) {
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
///
-/// \param firstQualifierLookup - the entity found by unqualified lookup
-/// for the first name in the qualifier, if this is for a member expression
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
bool recursive) {
// x, ::x
@@ -817,7 +832,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@@ -825,7 +840,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
break;
case NestedNameSpecifier::NamespaceAlias:
if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@@ -842,193 +857,26 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// - a template template parameter with arguments
// In all of these cases, we should have no prefix.
if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
} else {
// Otherwise, all the cases want this.
Out << "sr";
}
- // Only certain other types are valid as prefixes; enumerate them.
- switch (type->getTypeClass()) {
- case Type::Builtin:
- case Type::Complex:
- case Type::Adjusted:
- case Type::Decayed:
- case Type::Pointer:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- case Type::Enum:
- case Type::Paren:
- case Type::Elaborated:
- case Type::Attributed:
- case Type::Auto:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- llvm_unreachable("type is illegal as a nested name specifier");
-
- case Type::SubstTemplateTypeParmPack:
- // FIXME: not clear how to mangle this!
- // template <class T...> class A {
- // template <class U...> void foo(decltype(T::foo(U())) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
-
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <template-template-param> <template-args>
- // (this last is not official yet)
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::TemplateTypeParm:
- case Type::UnaryTransform:
- case Type::SubstTemplateTypeParm:
- unresolvedType:
- assert(!qualifier->getPrefix());
-
- // We only get here recursively if we're followed by identifiers.
- if (recursive) Out << 'N';
-
- // This seems to do everything we want. It's not really
- // sanctioned for a substituted template parameter, though.
- mangleType(QualType(type, 0));
-
- // We never want to print 'E' directly after an unresolved-type,
- // so we return directly.
+ if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : ""))
return;
- case Type::Typedef:
- mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::UnresolvedUsing:
- mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::Record:
- mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::TemplateSpecialization: {
- const TemplateSpecializationType *tst
- = cast<TemplateSpecializationType>(type);
- TemplateName name = tst->getTemplateName();
- switch (name.getKind()) {
- case TemplateName::Template:
- case TemplateName::QualifiedTemplate: {
- TemplateDecl *temp = name.getAsTemplateDecl();
-
- // If the base is a template template parameter, this is an
- // unresolved type.
- assert(temp && "no template for template specialization type");
- if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
-
- mangleSourceName(temp->getIdentifier());
- break;
- }
-
- case TemplateName::OverloadedTemplate:
- case TemplateName::DependentTemplate:
- llvm_unreachable("invalid base for a template specialization type");
-
- case TemplateName::SubstTemplateTemplateParm: {
- SubstTemplateTemplateParmStorage *subst
- = name.getAsSubstTemplateTemplateParm();
- mangleExistingSubstitution(subst->getReplacement());
- break;
- }
-
- case TemplateName::SubstTemplateTemplateParmPack: {
- // FIXME: not clear how to mangle this!
- // template <template <class U> class T...> class A {
- // template <class U...> void foo(decltype(T<U>::foo) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
- }
- }
-
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
-
- case Type::InjectedClassName:
- mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::DependentName:
- mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
- break;
-
- case Type::DependentTemplateSpecialization: {
- const DependentTemplateSpecializationType *tst
- = cast<DependentTemplateSpecializationType>(type);
- mangleSourceName(tst->getIdentifier());
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
- }
break;
}
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
- if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ if (qualifier->getPrefix())
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
- } else if (firstQualifierLookup) {
-
- // Try to make a proper qualifier out of the lookup result, and
- // then just recurse on that.
- NestedNameSpecifier *newQualifier;
- if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
- QualType type = getASTContext().getTypeDeclType(typeDecl);
-
- // Pretend we had a different nested name specifier.
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- /*template*/ false,
- type.getTypePtr());
- } else if (NamespaceDecl *nspace =
- dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- nspace);
- } else if (NamespaceAliasDecl *alias =
- dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- alias);
- } else {
- // No sensible mangling to do here.
- newQualifier = nullptr;
- }
-
- if (newQualifier)
- return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
- recursive);
-
- } else {
+ else
Out << "sr";
- }
mangleSourceName(qualifier->getAsIdentifier());
break;
@@ -1043,16 +891,41 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity) {
- if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
- mangleUnqualifiedName(nullptr, name, knownArity);
+ if (qualifier) mangleUnresolvedPrefix(qualifier);
+ switch (name.getNameKind()) {
+ // <base-unresolved-name> ::= <simple-id>
+ case DeclarationName::Identifier:
+ mangleSourceName(name.getAsIdentifierInfo());
+ break;
+ // <base-unresolved-name> ::= dn <destructor-name>
+ case DeclarationName::CXXDestructorName:
+ Out << "dn";
+ mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
+ break;
+ // <base-unresolved-name> ::= on <operator-name>
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXOperatorName:
+ Out << "on";
+ mangleOperatorName(name, knownArity);
+ break;
+ case DeclarationName::CXXConstructorName:
+ llvm_unreachable("Can't mangle a constructor name!");
+ case DeclarationName::CXXUsingDirective:
+ llvm_unreachable("Can't mangle a using directive name!");
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCZeroArgSelector:
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
+ }
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name,
unsigned KnownArity) {
+ unsigned Arity = KnownArity;
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
@@ -1163,7 +1036,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
Str += llvm::utostr(AnonStructId);
Out << Str.size();
- Out << Str.str();
+ Out << Str;
break;
}
@@ -1194,33 +1067,19 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
mangleCXXDtorType(Dtor_Complete);
break;
- case DeclarationName::CXXConversionFunctionName:
- // <operator-name> ::= cv <type> # (cast)
- Out << "cv";
- mangleType(Name.getCXXNameType());
- break;
-
- case DeclarationName::CXXOperatorName: {
- unsigned Arity;
- if (ND) {
+ case DeclarationName::CXXOperatorName:
+ if (ND && Arity == UnknownArity) {
Arity = cast<FunctionDecl>(ND)->getNumParams();
- // If we have a C++ member function, we need to include the 'this' pointer.
- // FIXME: This does not make sense for operators that are static, but their
- // names stay the same regardless of the arity (operator new for instance).
- if (isa<CXXMethodDecl>(ND))
- Arity++;
- } else
- Arity = KnownArity;
-
- mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
- break;
- }
-
+ // If we have a member function, we need to include the 'this' pointer.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
+ if (!MD->isStatic())
+ Arity++;
+ }
+ // FALLTHROUGH
+ case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXLiteralOperatorName:
- // FIXME: This mangling is not yet official.
- Out << "li";
- mangleSourceName(Name.getCXXLiteralIdentifier());
+ mangleOperatorName(Name, Arity);
break;
case DeclarationName::CXXUsingDirective:
@@ -1529,7 +1388,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
assert(Dependent && "Unknown template name kind?");
- manglePrefix(Dependent->getQualifier());
+ if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
+ manglePrefix(Qualifier);
mangleUnscopedTemplateName(Template);
}
@@ -1591,7 +1451,7 @@ void CXXNameMangler::mangleType(TemplateName TN) {
// <class-enum-type> ::= <name>
// <name> ::= <nested-name>
- mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr);
+ mangleUnresolvedPrefix(Dependent->getQualifier());
mangleSourceName(Dependent->getIdentifier());
break;
}
@@ -1620,6 +1480,181 @@ void CXXNameMangler::mangleType(TemplateName TN) {
addSubstitution(TN);
}
+bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
+ StringRef Prefix) {
+ // Only certain other types are valid as prefixes; enumerate them.
+ switch (Ty->getTypeClass()) {
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Adjusted:
+ case Type::Decayed:
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Paren:
+ case Type::Attributed:
+ case Type::Auto:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ case Type::Atomic:
+ llvm_unreachable("type is illegal as a nested name specifier");
+
+ case Type::SubstTemplateTypeParmPack:
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(decltype(T::foo(U())) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <template-template-param> <template-args>
+ // (this last is not official yet)
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::TemplateTypeParm:
+ case Type::UnaryTransform:
+ case Type::SubstTemplateTypeParm:
+ unresolvedType:
+ // Some callers want a prefix before the mangled type.
+ Out << Prefix;
+
+ // This seems to do everything we want. It's not really
+ // sanctioned for a substituted template parameter, though.
+ mangleType(Ty);
+
+ // We never want to print 'E' directly after an unresolved-type,
+ // so we return directly.
+ return true;
+
+ case Type::Typedef:
+ mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::UnresolvedUsing:
+ mangleSourceName(
+ cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::Enum:
+ case Type::Record:
+ mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(Ty);
+ TemplateName TN = TST->getTemplateName();
+ switch (TN.getKind()) {
+ case TemplateName::Template:
+ case TemplateName::QualifiedTemplate: {
+ TemplateDecl *TD = TN.getAsTemplateDecl();
+
+ // If the base is a template template parameter, this is an
+ // unresolved type.
+ assert(TD && "no template for template specialization type");
+ if (isa<TemplateTemplateParmDecl>(TD))
+ goto unresolvedType;
+
+ mangleSourceName(TD->getIdentifier());
+ break;
+ }
+
+ case TemplateName::OverloadedTemplate:
+ case TemplateName::DependentTemplate:
+ llvm_unreachable("invalid base for a template specialization type");
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst =
+ TN.getAsSubstTemplateTemplateParm();
+ mangleExistingSubstitution(subst->getReplacement());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ // FIXME: not clear how to mangle this!
+ // template <template <class U> class T...> class A {
+ // template <class U...> void foo(decltype(T<U>::foo) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+ }
+ }
+
+ mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+ break;
+ }
+
+ case Type::InjectedClassName:
+ mangleSourceName(
+ cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::DependentName:
+ mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
+ break;
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *DTST =
+ cast<DependentTemplateSpecializationType>(Ty);
+ mangleSourceName(DTST->getIdentifier());
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ break;
+ }
+
+ case Type::Elaborated:
+ return mangleUnresolvedTypeOrSimpleId(
+ cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
+ }
+
+ return false;
+}
+
+void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXUsingDirective:
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCZeroArgSelector:
+ llvm_unreachable("Not an operator name");
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= cv <type> # (cast)
+ Out << "cv";
+ mangleType(Name.getCXXNameType());
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ Out << "li";
+ mangleSourceName(Name.getCXXLiteralIdentifier());
+ return;
+
+ case DeclarationName::CXXOperatorName:
+ mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
+ break;
+ }
+}
+
+
+
void
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
switch (OO) {
@@ -1975,7 +2010,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::Half: Out << "Dh"; break;
case BuiltinType::Float: Out << 'f'; break;
case BuiltinType::Double: Out << 'd'; break;
- case BuiltinType::LongDouble: Out << 'e'; break;
+ case BuiltinType::LongDouble:
+ Out << (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble()
+ ? 'g'
+ : 'e');
+ break;
case BuiltinType::NullPtr: Out << "Dn"; break;
#define BUILTIN_TYPE(Id, SingletonId)
@@ -2276,6 +2315,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
EltName = "Poly16";
break;
case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
EltName = "Poly64";
break;
default:
@@ -2339,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;
@@ -2351,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) {
@@ -2519,6 +2572,29 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
+void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
+ // Ignore member expressions involving anonymous unions.
+ while (const auto *RT = Base->getType()->getAs<RecordType>()) {
+ if (!RT->getDecl()->isAnonymousStructOrUnion())
+ break;
+ const auto *ME = dyn_cast<MemberExpr>(Base);
+ if (!ME)
+ break;
+ Base = ME->getBase();
+ IsArrow = ME->isArrow();
+ }
+
+ if (Base->isImplicitCXXThis()) {
+ // Note: GCC mangles member expressions to the implicit 'this' as
+ // *this., whereas we represent them as this->. The Itanium C++ ABI
+ // does not specify anything here, so we follow GCC.
+ Out << "dtdefpT";
+ } else {
+ Out << (IsArrow ? "pt" : "dt");
+ mangleExpression(Base);
+ }
+}
+
/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
@@ -2528,30 +2604,9 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
- if (base) {
-
- // Ignore member expressions involving anonymous unions.
- while (const auto *RT = base->getType()->getAs<RecordType>()) {
- if (!RT->getDecl()->isAnonymousStructOrUnion())
- break;
- const auto *ME = dyn_cast<MemberExpr>(base);
- if (!ME)
- break;
- base = ME->getBase();
- isArrow = ME->isArrow();
- }
-
- if (base->isImplicitCXXThis()) {
- // Note: GCC mangles member expressions to the implicit 'this' as
- // *this., whereas we represent them as this->. The Itanium C++ ABI
- // does not specify anything here, so we follow GCC.
- Out << "dtdefpT";
- } else {
- Out << (isArrow ? "pt" : "dt");
- mangleExpression(base);
- }
- }
- mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
+ if (base)
+ mangleMemberExprBase(base, isArrow);
+ mangleUnresolvedName(qualifier, member, arity);
}
/// Look at the callee of the given call expression and determine if
@@ -2592,6 +2647,13 @@ void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding)
mangleExpression(ECE->getSubExpr());
}
+void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
+ if (auto *Syntactic = InitList->getSyntacticForm())
+ InitList = Syntactic;
+ for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
+ mangleExpression(InitList->getInit(i));
+}
+
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
@@ -2631,8 +2693,9 @@ recurse:
// These all can only appear in local or variable-initialization
// contexts and so should never appear in a mangling.
case Expr::AddrLabelExprClass:
- case Expr::DesignatedInitExprClass:
+ case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
+ case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
@@ -2641,9 +2704,9 @@ recurse:
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
- case Expr::CXXPseudoDestructorExprClass:
case Expr::ChooseExprClass:
case Expr::CompoundLiteralExprClass:
+ case Expr::DesignatedInitExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::GenericSelectionExprClass:
case Expr::ObjCEncodeExprClass:
@@ -2713,9 +2776,7 @@ recurse:
case Expr::InitListExprClass: {
Out << "il";
- const InitListExpr *InitList = cast<InitListExpr>(E);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
+ mangleInitListElements(cast<InitListExpr>(E));
Out << "E";
break;
}
@@ -2759,9 +2820,14 @@ recurse:
Out << "cl";
}
- mangleExpression(CE->getCallee(), CE->getNumArgs());
- for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
- mangleExpression(CE->getArg(I));
+ unsigned CallArity = CE->getNumArgs();
+ for (const Expr *Arg : CE->arguments())
+ if (isa<PackExpansionExpr>(Arg))
+ CallArity = UnknownArity;
+
+ mangleExpression(CE->getCallee(), CallArity);
+ for (const Expr *Arg : CE->arguments())
+ mangleExpression(Arg);
Out << 'E';
break;
}
@@ -2793,9 +2859,7 @@ recurse:
} else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&
isa<InitListExpr>(Init)) {
// Only take InitListExprs apart for list-initialization.
- const InitListExpr *InitList = cast<InitListExpr>(Init);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
+ mangleInitListElements(cast<InitListExpr>(Init));
} else
mangleExpression(Init);
}
@@ -2803,6 +2867,33 @@ recurse:
break;
}
+ case Expr::CXXPseudoDestructorExprClass: {
+ const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
+ if (const Expr *Base = PDE->getBase())
+ mangleMemberExprBase(Base, PDE->isArrow());
+ NestedNameSpecifier *Qualifier = PDE->getQualifier();
+ QualType ScopeType;
+ if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
+ if (Qualifier) {
+ mangleUnresolvedPrefix(Qualifier,
+ /*Recursive=*/true);
+ mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
+ Out << 'E';
+ } else {
+ Out << "sr";
+ if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
+ Out << 'E';
+ }
+ } else if (Qualifier) {
+ mangleUnresolvedPrefix(Qualifier);
+ }
+ // <base-unresolved-name> ::= dn <destructor-name>
+ Out << "dn";
+ QualType DestroyedType = PDE->getDestroyedType();
+ mangleUnresolvedTypeOrSimpleId(DestroyedType);
+ break;
+ }
+
case Expr::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
@@ -2813,9 +2904,9 @@ recurse:
case Expr::UnresolvedMemberExprClass: {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), nullptr, ME->getMemberName(),
- Arity);
+ mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
+ ME->isArrow(), ME->getQualifier(), nullptr,
+ ME->getMemberName(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
@@ -2824,8 +2915,9 @@ recurse:
case Expr::CXXDependentScopeMemberExprClass: {
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), ME->getFirstQualifierFoundInScope(),
+ mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
+ ME->isArrow(), ME->getQualifier(),
+ ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
@@ -2834,7 +2926,7 @@ recurse:
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity);
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -2856,26 +2948,55 @@ recurse:
break;
}
- case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXConstructExprClass: {
- const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
+ const auto *CE = cast<CXXConstructExpr>(E);
+ if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
+ assert(
+ CE->getNumArgs() >= 1 &&
+ (CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) &&
+ "implicit CXXConstructExpr must have one argument");
+ return mangleExpression(cast<CXXConstructExpr>(E)->getArg(0));
+ }
+ Out << "il";
+ for (auto *E : CE->arguments())
+ mangleExpression(E);
+ Out << "E";
+ break;
+ }
+
+ case Expr::CXXTemporaryObjectExprClass: {
+ const auto *CE = cast<CXXTemporaryObjectExpr>(E);
unsigned N = CE->getNumArgs();
+ bool List = CE->isListInitialization();
- if (CE->isListInitialization())
+ if (List)
Out << "tl";
else
Out << "cv";
mangleType(CE->getType());
- if (N != 1) Out << '_';
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
- if (N != 1) Out << 'E';
+ if (!List && N != 1)
+ Out << '_';
+ if (CE->isStdInitListInitialization()) {
+ // We implicitly created a std::initializer_list<T> for the first argument
+ // of a constructor of type U in an expression of the form U{a, b, c}.
+ // Strip all the semantic gunk off the initializer list.
+ auto *SILE =
+ cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit());
+ auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit());
+ mangleInitListElements(ILE);
+ } else {
+ for (auto *E : CE->arguments())
+ mangleExpression(E);
+ }
+ if (List || N != 1)
+ Out << 'E';
break;
}
case Expr::CXXScalarValueInitExprClass:
- Out <<"cv";
+ Out << "cv";
mangleType(E->getType());
- Out <<"_E";
+ Out << "_E";
break;
case Expr::CXXNoexceptExprClass:
@@ -2910,13 +3031,21 @@ recurse:
case UETT_AlignOf:
Out << 'a';
break;
- case UETT_VecStep:
+ case UETT_VecStep: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle vec_step expression");
Diags.Report(DiagID);
return;
}
+ case UETT_OpenMPRequiredSimdAlign:
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot yet mangle __builtin_omp_required_simd_align expression");
+ Diags.Report(DiagID);
+ return;
+ }
if (SAE->isArgumentType()) {
Out << 't';
mangleType(SAE->getArgumentType());
@@ -3020,10 +3149,28 @@ recurse:
// Fall through to mangle the cast itself.
case Expr::CStyleCastExprClass:
- case Expr::CXXFunctionalCastExprClass:
mangleCastExpression(E, "cv");
break;
+ case Expr::CXXFunctionalCastExprClass: {
+ auto *Sub = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreImplicit();
+ // FIXME: Add isImplicit to CXXConstructExpr.
+ if (auto *CCE = dyn_cast<CXXConstructExpr>(Sub))
+ if (CCE->getParenOrBraceRange().isInvalid())
+ Sub = CCE->getArg(0)->IgnoreImplicit();
+ if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub))
+ Sub = StdInitList->getSubExpr()->IgnoreImplicit();
+ if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
+ Out << "tl";
+ mangleType(E->getType());
+ mangleInitListElements(IL);
+ Out << "E";
+ } else {
+ mangleCastExpression(E, "cv");
+ }
+ break;
+ }
+
case Expr::CXXStaticCastExprClass:
mangleCastExpression(E, "sc");
break;
@@ -3058,7 +3205,7 @@ recurse:
default:
// <expr-primary> ::= L <mangled-name> E # external name
Out << 'L';
- mangle(D, "_Z");
+ mangle(D);
Out << 'E';
break;
@@ -3101,8 +3248,7 @@ recurse:
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
- Arity);
+ mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -3327,6 +3473,9 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
case Ctor_Comdat:
Out << "C5";
break;
+ case Ctor_DefaultClosure:
+ case Ctor_CopyingClosure:
+ llvm_unreachable("closure constructors don't exist for the Itanium ABI!");
}
}
@@ -3410,8 +3559,8 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
const ValueDecl *D = DRE->getDecl();
if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
- Out << "L";
- mangle(D, "_Z");
+ Out << 'L';
+ mangle(D);
Out << 'E';
break;
}
@@ -3440,13 +3589,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
Out << 'L';
// References to external entities use the mangled name; if the name would
// not normally be manged then mangle it as unqualified.
- //
- // FIXME: The ABI specifies that external names here should have _Z, but
- // gcc leaves this off.
- if (compensateMangling)
- mangle(D, "_Z");
- else
- mangle(D, "Z");
+ mangle(D);
Out << 'E';
if (compensateMangling)
@@ -3524,8 +3667,8 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
-/// \brief Determine whether the given type has any qualifiers that are
-/// relevant for substitutions.
+/// Determine whether the given type has any qualifiers that are relevant for
+/// substitutions.
static bool hasMangledSubstitutionQualifiers(QualType T) {
Qualifiers Qs = T.getQualifiers();
return Qs.getCVRQualifiers() || Qs.hasAddressSpace();
@@ -3571,8 +3714,8 @@ static bool isCharType(QualType T) {
T->isSpecificBuiltinType(BuiltinType::Char_U);
}
-/// isCharSpecialization - Returns whether a given type is a template
-/// specialization of a given name with a single argument of type char.
+/// Returns whether a given type is a template specialization of a given name
+/// with a single argument of type char.
static bool isCharSpecialization(QualType T, const char *Name) {
if (T.isNull())
return false;
@@ -3722,8 +3865,8 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
//
-/// \brief Mangles the name of the declaration D and emits that name to the
-/// given output stream.
+/// Mangles the name of the declaration D and emits that name to the given
+/// output stream.
///
/// If the declaration D requires a mangled name, this routine will emit that
/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
@@ -3815,8 +3958,7 @@ void ItaniumMangleContextImpl::mangleCXXDtorThunk(
Mangler.mangleFunctionEncoding(DD);
}
-/// mangleGuardVariable - Returns the mangled name for a guard variable
-/// for the passed in VarDecl.
+/// Returns the mangled name for a guard variable for the passed in VarDecl.
void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= GV <object name> # Guard variable for one-time
@@ -3845,6 +3987,26 @@ void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
Mangler.getStream() << D->getName();
}
+void ItaniumMangleContextImpl::mangleSEHFilterExpression(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__filt_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
+void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__fin_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= TH <object name>
@@ -3923,6 +4085,21 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
mangleCXXRTTIName(Ty, Out);
}
+void ItaniumMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ if (!RD->isExternallyVisible()) {
+ // This part of the identifier needs to be unique across all translation
+ // units in the linked program. The scheme fails if multiple translation
+ // units are compiled using the same relative source file path, or if
+ // multiple translation units are built from the same source file.
+ SourceManager &SM = getASTContext().getSourceManager();
+ Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]";
+ }
+
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.mangleType(QualType(RD->getTypeForDecl(), 0));
+}
+
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {
llvm_unreachable("Can't mangle string literals");
}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
index 0603d3b..aba6796 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -31,11 +31,12 @@ class MicrosoftNumberingContext : public MangleNumberingContext {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
unsigned LambdaManglingNumber;
unsigned StaticLocalNumber;
+ unsigned StaticThreadlocalNumber;
public:
MicrosoftNumberingContext()
: MangleNumberingContext(), LambdaManglingNumber(0),
- StaticLocalNumber(0) {}
+ StaticLocalNumber(0), StaticThreadlocalNumber(0) {}
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
return ++LambdaManglingNumber;
@@ -47,6 +48,8 @@ public:
}
unsigned getStaticLocalNumber(const VarDecl *VD) override {
+ if (VD->getTLSKind())
+ return ++StaticThreadlocalNumber;
return ++StaticLocalNumber;
}
@@ -63,6 +66,10 @@ public:
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
+ llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
+ llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
+ CtorToDefaultArgExpr;
+
public:
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
@@ -82,13 +89,36 @@ public:
return false;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
+
// In the Microsoft ABI, classes can have one or two vtable pointers.
- CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits PointerSize =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize ||
Layout.getNonVirtualSize() == PointerSize * 2;
- }
+ }
+
+ void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) override {
+ CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
+ }
+
+ Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) override {
+ return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
+ }
+
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return RecordToCopyCtor[RD];
+ }
+
+ void
+ addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {
+ assert(CD != nullptr);
+ assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
+ RecordToCopyCtor[RD] = CD;
+ }
MangleNumberingContext *createMangleNumberingContext() const override {
return new MicrosoftNumberingContext();
@@ -149,8 +179,9 @@ MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const {
// // slot.
// void *FunctionPointerOrVirtualThunk;
//
-// // An offset to add to the address of the vbtable pointer after (possibly)
-// // selecting the virtual base but before resolving and calling the function.
+// // An offset to add to the address of the vbtable pointer after
+// // (possibly) selecting the virtual base but before resolving and calling
+// // the function.
// // Only needed if the class has any virtual bases or bases at a non-zero
// // offset.
// int NonVirtualBaseAdjustment;
@@ -186,29 +217,28 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
const MemberPointerType *MPT) const {
- const TargetInfo &Target = Context.getTargetInfo();
- assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
- Target.getTriple().getArch() == llvm::Triple::x86_64);
- unsigned Ptrs, Ints;
- std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
// The nominal struct is laid out with pointers followed by ints and aligned
// to a pointer width if any are present and an int width otherwise.
+ const TargetInfo &Target = Context.getTargetInfo();
unsigned PtrSize = Target.getPointerWidth(0);
unsigned IntSize = Target.getIntWidth();
+
+ unsigned Ptrs, Ints;
+ std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
unsigned Align;
// When MSVC does x86_32 record layout, it aligns aggregate member pointers to
// 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
// function memptrs.
- if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86)
- Align = 8 * 8;
+ if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
+ Align = 64;
else if (Ptrs)
Align = Target.getPointerAlign(0);
else
Align = Target.getIntAlign();
- if (Target.getTriple().getArch() == llvm::Triple::x86_64)
+ if (Target.getTriple().isArch64Bit())
Width = llvm::RoundUpToAlignment(Width, Align);
return std::make_pair(Width, Align);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index 72f90f6..48a8fa5 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -67,11 +67,15 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
return getEffectiveDeclContext(cast<Decl>(DC));
}
-static const FunctionDecl *getStructor(const FunctionDecl *fn) {
- if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
- return ftd->getTemplatedDecl();
+static const FunctionDecl *getStructor(const NamedDecl *ND) {
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ return FTD->getTemplatedDecl();
- return fn;
+ const auto *FD = cast<FunctionDecl>(ND);
+ if (const auto *FTD = FD->getPrimaryTemplate())
+ return FTD->getTemplatedDecl();
+
+ return FD;
}
static bool isLambda(const NamedDecl *ND) {
@@ -89,6 +93,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -109,6 +115,19 @@ public:
void mangleCXXVBTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
+ void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
+ const CXXRecordDecl *DstRD,
+ raw_ostream &Out) override;
+ void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
+ uint32_t NumEntries, raw_ostream &Out) override;
+ void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
+ raw_ostream &Out) override;
+ void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
+ CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
+ int32_t VBPtrOffset, uint32_t VBIndex,
+ raw_ostream &Out) override;
+ void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
+ raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -131,10 +150,18 @@ public:
void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
+ void mangleThreadSafeStaticGuardVariable(const VarDecl *D, unsigned GuardNum,
+ raw_ostream &Out) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
+ void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
+ void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -211,6 +238,12 @@ public:
64) {}
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
+ const CXXConstructorDecl *D, CXXCtorType Type)
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
+
+ MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
@@ -220,7 +253,7 @@ public:
void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
void mangleName(const NamedDecl *ND);
- void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD);
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
@@ -247,7 +280,7 @@ private:
void mangleQualifiers(Qualifiers Quals, bool IsMember);
void mangleRefQualifier(RefQualifierKind RefQualifier);
void manglePointerCVQualifiers(Qualifiers Quals);
- void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType);
+ void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
void
@@ -261,6 +294,7 @@ private:
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
+ Qualifiers Quals, \
SourceRange Range);
#include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE
@@ -271,6 +305,7 @@ private:
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
+ void mangleCallingConvention(CallingConv CC);
void mangleCallingConvention(const FunctionType *T);
void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
void mangleExpression(const Expr *E);
@@ -352,7 +387,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
Out << Prefix;
mangleName(D);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
+ mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
else {
@@ -365,7 +400,8 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
}
}
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
+ bool ShouldMangle) {
// <type-encoding> ::= <function-class> <function-type>
// Since MSVC operates on the type as written and not the canonical type, it
@@ -380,13 +416,20 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// extern "C" functions can hold entities that must be mangled.
// As it stands, these functions still need to get expressed in the full
// external name. They have their class and type omitted, replaced with '9'.
- if (Context.shouldMangleDeclName(FD)) {
- // First, the function class.
+ if (ShouldMangle) {
+ // We would like to mangle all extern "C" functions using this additional
+ // component but this would break compatibility with MSVC's behavior.
+ // Instead, do this when we know that compatibility isn't important (in
+ // other words, when it is an overloaded extern "C" funciton).
+ if (FD->isExternC() && FD->hasAttr<OverloadableAttr>())
+ Out << "$$J0";
+
mangleFunctionClass(FD);
mangleFunctionType(FT, FD);
- } else
+ } else {
Out << '9';
+ }
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -422,7 +465,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
Ty->isMemberPointerType()) {
mangleType(Ty, SR, QMM_Drop);
manglePointerExtQualifiers(
- Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr);
+ Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), QualType());
if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
// Member pointers are suffixed with a back reference to the member
@@ -459,6 +502,9 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD,
FieldOffset /= getASTContext().getCharWidth();
VBTableOffset = 0;
+
+ if (IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+ FieldOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
@@ -525,8 +571,12 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
}
} else {
mangleName(MD);
- mangleFunctionEncoding(MD);
+ mangleFunctionEncoding(MD, /*ShouldMangle=*/true);
}
+
+ if (VBTableOffset == 0 &&
+ IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+ NVOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
// Null single inheritance member functions are encoded as a simple nullptr.
if (IM == MSInheritanceAttr::Keyword_single_inheritance) {
@@ -539,7 +589,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
}
if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM))
- mangleNumber(NVOffset);
+ mangleNumber(static_cast<uint32_t>(NVOffset));
if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
mangleNumber(VBPtrOffset);
if (MSInheritanceAttr::hasVBTableOffsetField(IM))
@@ -559,7 +609,7 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
Out << "$B";
mangleNumber(OffsetInVFTable);
Out << 'A';
- Out << (PointersAre64Bit ? 'A' : 'E');
+ mangleCallingConvention(MD->getType()->getAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
@@ -757,12 +807,18 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
llvm_unreachable("Can't mangle Objective-C selector names here!");
case DeclarationName::CXXConstructorName:
- if (ND == Structor) {
- assert(StructorType == Ctor_Complete &&
- "Should never be asked to mangle a ctor other than complete");
+ if (Structor == getStructor(ND)) {
+ if (StructorType == Ctor_CopyingClosure) {
+ Out << "?_O";
+ return;
+ }
+ if (StructorType == Ctor_DefaultClosure) {
+ Out << "?_F";
+ return;
+ }
}
Out << "?0";
- break;
+ return;
case DeclarationName::CXXDestructorName:
if (ND == Structor)
@@ -1134,10 +1190,13 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
cast<ValueDecl>(ND));
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- if (MD && MD->isInstance())
+ if (MD && MD->isInstance()) {
mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD);
- else
- mangle(FD, "$1?");
+ } else {
+ Out << "$1?";
+ mangleName(FD);
+ mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
+ }
} else {
mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
}
@@ -1156,11 +1215,23 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
return;
}
if (MPT->isMemberDataPointer()) {
- mangleMemberDataPointer(RD, nullptr);
- return;
+ if (isa<ClassTemplateDecl>(TD)) {
+ mangleMemberDataPointer(RD, nullptr);
+ return;
+ }
+ // nullptr data pointers are always represented with a single field
+ // which is initialized with either 0 or -1. Why -1? Well, we need to
+ // distinguish the case where the data member is at offset zero in the
+ // record.
+ // However, we are free to use 0 *if* we would use multiple fields for
+ // non-nullptr member pointers.
+ if (!RD->nullFieldOffsetIsZero()) {
+ mangleIntegerLiteral(llvm::APSInt::get(-1), /*IsBoolean=*/false);
+ return;
+ }
}
}
- Out << "$0A@";
+ mangleIntegerLiteral(llvm::APSInt::getUnsigned(0), /*IsBoolean=*/false);
break;
}
case TemplateArgument::Expression:
@@ -1171,7 +1242,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
if (TemplateArgs.empty()) {
if (isa<TemplateTypeParmDecl>(Parm) ||
isa<TemplateTemplateParmDecl>(Parm))
- Out << "$$V";
+ // MSVC 2015 changed the mangling for empty expanded template packs,
+ // use the old mangling for link compatibility for old versions.
+ Out << (Context.getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2015)
+ ? "$$V"
+ : "$$$V");
else if (isa<NonTypeTemplateParmDecl>(Parm))
Out << "$S";
else
@@ -1298,11 +1374,11 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
}
}
-void
-MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
- const Type *PointeeType) {
+void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
+ QualType PointeeType) {
bool HasRestrict = Quals.hasRestrict();
- if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType()))
+ if (PointersAre64Bit &&
+ (PointeeType.isNull() || !PointeeType->isFunctionType()))
Out << 'E';
if (HasRestrict)
@@ -1338,29 +1414,38 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
// e.g.
// void (*x)(void) will not form a backreference with void x(void)
void *TypePtr;
- if (const DecayedType *DT = T->getAs<DecayedType>()) {
- TypePtr = DT->getOriginalType().getCanonicalType().getAsOpaquePtr();
+ if (const auto *DT = T->getAs<DecayedType>()) {
+ QualType OriginalType = DT->getOriginalType();
+ // All decayed ArrayTypes should be treated identically; as-if they were
+ // a decayed IncompleteArrayType.
+ if (const auto *AT = getASTContext().getAsArrayType(OriginalType))
+ OriginalType = getASTContext().getIncompleteArrayType(
+ AT->getElementType(), AT->getSizeModifier(),
+ AT->getIndexTypeCVRQualifiers());
+
+ TypePtr = OriginalType.getCanonicalType().getAsOpaquePtr();
// If the original parameter was textually written as an array,
// instead treat the decayed parameter like it's const.
//
// e.g.
// int [] -> int * const
- if (DT->getOriginalType()->isArrayType())
+ if (OriginalType->isArrayType())
T = T.withConst();
- } else
+ } else {
TypePtr = T.getCanonicalType().getAsOpaquePtr();
+ }
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
- size_t OutSizeBefore = Out.GetNumBytesInBuffer();
+ size_t OutSizeBefore = Out.tell();
mangleType(T, Range, QMM_Drop);
// See if it's worth creating a back reference.
// Only types longer than 1 character are considered
// and only 10 back references slots are available:
- bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);
+ bool LongerThanOneChar = (Out.tell() - OutSizeBefore > 1);
if (LongerThanOneChar && TypeBackReferences.size() < 10) {
size_t Size = TypeBackReferences.size();
TypeBackReferences[TypePtr] = Size;
@@ -1388,7 +1473,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
}
bool IsPointer = T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType();
+ T->isReferenceType() || T->isBlockPointerType();
switch (QMM) {
case QMM_Drop:
@@ -1415,11 +1500,6 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
break;
}
- // We have to mangle these now, while we still have enough information.
- if (IsPointer) {
- manglePointerCVQualifiers(Quals);
- manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr());
- }
const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
@@ -1430,7 +1510,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
- mangleType(cast<CLASS##Type>(ty), Range); \
+ mangleType(cast<CLASS##Type>(ty), Quals, Range); \
break;
#include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE
@@ -1439,7 +1519,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
}
}
-void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
+void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
SourceRange Range) {
// <type> ::= <builtin-type>
// <builtin-type> ::= X # void
@@ -1525,7 +1605,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
}
// <type> ::= <function-type>
-void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
+void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers,
SourceRange) {
// Structors only appear in decls, so at this point we know it's not a
// structor type.
@@ -1539,7 +1619,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
}
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Can't mangle K&R function prototypes");
}
@@ -1553,24 +1633,34 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
SourceRange Range;
if (D) Range = D->getSourceRange();
- bool IsStructor = false, HasThisQuals = ForceThisQuals;
+ bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false;
+ CallingConv CC = T->getCallConv();
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
if (MD->isInstance())
HasThisQuals = true;
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ if (isa<CXXDestructorDecl>(MD)) {
+ IsStructor = true;
+ } else if (isa<CXXConstructorDecl>(MD)) {
IsStructor = true;
+ IsCtorClosure = (StructorType == Ctor_CopyingClosure ||
+ StructorType == Ctor_DefaultClosure) &&
+ getStructor(MD) == Structor;
+ if (IsCtorClosure)
+ CC = getASTContext().getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+ }
}
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (HasThisQuals) {
Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals());
- manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr);
+ manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, /*IsMember=*/false);
}
- mangleCallingConvention(T);
+ mangleCallingConvention(CC);
// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
@@ -1584,6 +1674,29 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
+ if (IsCtorClosure) {
+ // Default constructor closure and copy constructor closure both return
+ // void.
+ Out << 'X';
+
+ if (StructorType == Ctor_DefaultClosure) {
+ // Default constructor closure always has no arguments.
+ Out << 'X';
+ } else if (StructorType == Ctor_CopyingClosure) {
+ // Copy constructor closure always takes an unqualified reference.
+ mangleArgumentType(getASTContext().getLValueReferenceType(
+ Proto->getParamType(0)
+ ->getAs<LValueReferenceType>()
+ ->getPointeeType(),
+ /*SpelledAsLValue=*/true),
+ Range);
+ Out << '@';
+ } else {
+ llvm_unreachable("unexpected constructor closure!");
+ }
+ Out << 'Z';
+ return;
+ }
Out << '@';
} else {
QualType ResultType = Proto->getReturnType();
@@ -1608,7 +1721,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (const QualType Arg : Proto->param_types())
+ for (const QualType &Arg : Proto->param_types())
mangleArgumentType(Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
@@ -1673,10 +1786,11 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
else
Out << 'Q';
}
- } else
+ } else {
Out << 'Y';
+ }
}
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
+void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// <calling-convention> ::= A # __cdecl
// ::= B # __export __cdecl
// ::= C # __pascal
@@ -1693,7 +1807,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
// that keyword. (It didn't actually export them, it just made them so
// that they could be in a DLL and somebody from another module could call
// them.)
- CallingConv CC = T->getCallConv();
+
switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
@@ -1707,6 +1821,9 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
case CC_X86VectorCall: Out << 'Q'; break;
}
}
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
+ mangleCallingConvention(T->getCallConv());
+}
void MicrosoftCXXNameMangler::mangleThrowSpecification(
const FunctionProtoType *FT) {
// <throw-spec> ::= Z # throw(...) (default)
@@ -1719,7 +1836,7 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification(
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
// Probably should be mangled as a template instantiation; need to see what
// VC does first.
DiagnosticsEngine &Diags = Context.getDiags();
@@ -1734,10 +1851,12 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <struct-type> ::= U <name>
// <class-type> ::= V <name>
// <enum-type> ::= W4 <name>
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
+void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
+ SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
+void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
+ SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
@@ -1772,39 +1891,41 @@ void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) {
manglePointerCVQualifiers(T->getElementType().getQualifiers());
mangleType(T->getElementType(), SourceRange());
}
-void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
+void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
-void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
+void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
QualType ElementTy(T, 0);
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
- if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
+ if (ElementTy->isConstantArrayType()) {
+ const ConstantArrayType *CAT =
+ getASTContext().getAsConstantArrayType(ElementTy);
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
+ } else if (ElementTy->isIncompleteArrayType()) {
+ const IncompleteArrayType *IAT =
+ getASTContext().getAsIncompleteArrayType(ElementTy);
+ Dimensions.push_back(llvm::APInt(32, 0));
+ ElementTy = IAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
const VariableArrayType *VAT =
getASTContext().getAsVariableArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this variable-length array yet");
- Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)
- << VAT->getBracketsRange();
- return;
+ Dimensions.push_back(llvm::APInt(32, 0));
+ ElementTy = VAT->getElementType();
} else if (ElementTy->isDependentSizedArrayType()) {
// The dependent expression has to be folded into a constant (TODO).
const DependentSizedArrayType *DSAT =
@@ -1815,12 +1936,9 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
<< DSAT->getBracketsRange();
return;
- } else if (const IncompleteArrayType *IAT =
- getASTContext().getAsIncompleteArrayType(ElementTy)) {
- Dimensions.push_back(llvm::APInt(32, 0));
- ElementTy = IAT->getElementType();
+ } else {
+ break;
}
- else break;
}
Out << 'Y';
// <dimension-count> ::= <number> # number of extra dimensions
@@ -1833,9 +1951,11 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
// <type> ::= <pointer-to-member-type>
// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// <class name> <type>
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
+void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, Qualifiers Quals,
SourceRange Range) {
QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
@@ -1848,7 +1968,7 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
}
void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template type parameter type yet");
@@ -1856,9 +1976,8 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(
- const SubstTemplateTypeParmPackType *T,
- SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T,
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this substituted parameter pack yet");
@@ -1869,40 +1988,46 @@ void MicrosoftCXXNameMangler::mangleType(
// <type> ::= <pointer-type>
// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static pointers
-void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
+void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
SourceRange Range) {
- QualType PointeeTy = T->getPointeeType();
- mangleType(PointeeTy, Range);
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
- SourceRange Range) {
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
// Object pointers never have qualifiers.
Out << 'A';
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ mangleType(PointeeType, Range);
}
// <type> ::= <reference-type>
// <reference-type> ::= A E? <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static lvalue references
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
- SourceRange Range) {
- Out << 'A';
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ Out << (Quals.hasVolatile() ? 'B' : 'A');
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
// <type> ::= <r-value-reference-type>
// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static rvalue references
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
- SourceRange Range) {
- Out << "$$Q";
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ Out << (Quals.hasVolatile() ? "$$R" : "$$Q");
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
-void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
+void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1911,41 +2036,47 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
+void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
SourceRange Range) {
const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>();
assert(ET && "vectors with non-builtin elements are unsupported");
uint64_t Width = getASTContext().getTypeSize(T);
// Pattern match exactly the typedefs in our intrinsic headers. Anything that
// doesn't match the Intel types uses a custom mangling below.
- bool IntelVector = true;
- if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
- Out << "T__m64";
- } else if (Width == 128 || Width == 256) {
- if (ET->getKind() == BuiltinType::Float)
- Out << "T__m" << Width;
- else if (ET->getKind() == BuiltinType::LongLong)
- Out << "T__m" << Width << 'i';
- else if (ET->getKind() == BuiltinType::Double)
- Out << "U__m" << Width << 'd';
- else
- IntelVector = false;
+ bool IsBuiltin = true;
+ llvm::Triple::ArchType AT =
+ getASTContext().getTargetInfo().getTriple().getArch();
+ if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
+ if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
+ Out << "T__m64";
+ } else if (Width >= 128) {
+ if (ET->getKind() == BuiltinType::Float)
+ Out << "T__m" << Width;
+ else if (ET->getKind() == BuiltinType::LongLong)
+ Out << "T__m" << Width << 'i';
+ else if (ET->getKind() == BuiltinType::Double)
+ Out << "U__m" << Width << 'd';
+ else
+ IsBuiltin = false;
+ } else {
+ IsBuiltin = false;
+ }
} else {
- IntelVector = false;
+ IsBuiltin = false;
}
- if (!IntelVector) {
+ if (!IsBuiltin) {
// The MS ABI doesn't have a special mangling for vector types, so we define
// our own mangling to handle uses of __vector_size__ on user-specified
// types, and for extensions like __v4sf.
Out << "T__clang_vec" << T->getNumElements() << '_';
- mangleType(ET, Range);
+ mangleType(ET, Quals, Range);
}
Out << "@@";
}
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
+void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1954,7 +2085,7 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent-sized extended vector type yet");
@@ -1962,14 +2093,14 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,
+void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
// ObjC interfaces have structs underlying them.
Out << 'U';
mangleName(T->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
SourceRange Range) {
// We don't allow overloading by different protocol qualification,
// so mangling them isn't necessary.
@@ -1977,20 +2108,23 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
- SourceRange Range) {
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
+
Out << "_E";
- QualType pointee = T->getPointeeType();
- mangleFunctionType(pointee->castAs<FunctionProtoType>());
+ mangleFunctionType(PointeeType->castAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Cannot mangle injected class name type.");
}
void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template specialization type yet");
@@ -1998,7 +2132,7 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
+void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2008,8 +2142,8 @@ void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
}
void MicrosoftCXXNameMangler::mangleType(
- const DependentTemplateSpecializationType *T,
- SourceRange Range) {
+ const DependentTemplateSpecializationType *T, Qualifiers,
+ SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent template specialization type yet");
@@ -2017,7 +2151,7 @@ void MicrosoftCXXNameMangler::mangleType(
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
+void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2026,7 +2160,7 @@ void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
+void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2035,7 +2169,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
+void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2044,7 +2178,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
+void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2054,7 +2188,7 @@ void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
}
void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this unary transform type yet");
@@ -2062,7 +2196,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers,
+ SourceRange Range) {
assert(T->getDeducedType().isNull() && "expecting a dependent type!");
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2072,7 +2207,7 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
+void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2273,6 +2408,83 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
+void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T,
+ uint32_t Flags,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "llvm.eh.handlertype.";
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+ Mangler.getStream() << '.' << Flags;
+}
+
+void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap(
+ const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_K";
+ Mangler.mangleName(SrcRD);
+ Mangler.getStream() << "$C";
+ Mangler.mangleName(DstRD);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T,
+ bool IsConst,
+ bool IsVolatile,
+ uint32_t NumEntries,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_TI";
+ if (IsConst)
+ Mangler.getStream() << 'C';
+ if (IsVolatile)
+ Mangler.getStream() << 'V';
+ Mangler.getStream() << NumEntries;
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray(
+ QualType T, uint32_t NumEntries, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_CTA";
+ Mangler.getStream() << NumEntries;
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXCatchableType(
+ QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size,
+ uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_CT";
+
+ llvm::SmallString<64> RTTIMangling;
+ {
+ llvm::raw_svector_ostream Stream(RTTIMangling);
+ mangleCXXRTTI(T, Stream);
+ }
+ Mangler.getStream() << RTTIMangling.substr(1);
+
+ // VS2015 CTP6 omits the copy-constructor in the mangled name. This name is,
+ // in fact, superfluous but I'm not sure the change was made consciously.
+ // TODO: Revisit this when VS2015 gets released.
+ llvm::SmallString<64> CopyCtorMangling;
+ if (CD) {
+ llvm::raw_svector_ostream Stream(CopyCtorMangling);
+ mangleCXXCtor(CD, CT, Stream);
+ }
+ Mangler.getStream() << CopyCtorMangling.substr(1);
+
+ Mangler.getStream() << Size;
+ if (VBPtrOffset == -1) {
+ if (NVOffset) {
+ Mangler.getStream() << NVOffset;
+ }
+ } else {
+ Mangler.getStream() << NVOffset;
+ Mangler.getStream() << VBPtrOffset;
+ Mangler.getStream() << VBIndex;
+ }
+}
+
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
@@ -2318,6 +2530,28 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
Mangler.getStream() << '@';
}
+void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?filt$ <filter-number> @0
+ Mangler.getStream() << "\01?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
+void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?fin$ <filter-number> @0
+ Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
// This is just a made up unique string for the purposes of tbaa. undname
// does *not* know how to demangle it.
@@ -2329,7 +2563,7 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
CXXCtorType Type,
raw_ostream &Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
+ MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
mangler.mangle(D);
}
@@ -2348,18 +2582,18 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
getDiags().Report(VD->getLocation(), DiagID);
}
+void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
+ const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+
+ Mangler.getStream() << "\01?$TSS" << GuardNum << '@';
+ Mangler.mangleNestedName(VD);
+}
+
void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
raw_ostream &Out) {
- // TODO: This is not correct, especially with respect to VS "14". VS "14"
- // utilizes thread local variables to implement thread safe, re-entrant
- // initialization for statics. They no longer differentiate between an
- // externally visible and non-externally visible static with respect to
- // mangling, they all get $TSS <number>.
- //
- // N.B. This means that they can get more than 32 static variable guards in a
- // scope. It also means that they broke compatibility with their own ABI.
-
// <guard-name> ::= ?_B <postfix> @5 <scope-depth>
+ // ::= ?__J <postfix> @5 <scope-depth>
// ::= ?$S <guard-num> @ <postfix> @4IA
// The first mangling is what MSVC uses to guard static locals in inline
@@ -2371,8 +2605,11 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
MicrosoftCXXNameMangler Mangler(*this, Out);
bool Visible = VD->isExternallyVisible();
- // <operator-name> ::= ?_B # local static guard
- Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@");
+ if (Visible) {
+ Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B");
+ } else {
+ Mangler.getStream() << "\01?$S1@";
+ }
unsigned ScopeDepth = 0;
if (Visible && !getNextDiscriminator(VD, ScopeDepth))
// If we do not have a discriminator and are emitting a guard variable for
@@ -2553,6 +2790,21 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << '@';
}
+void MicrosoftMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ if (!RD->isExternallyVisible()) {
+ // This part of the identifier needs to be unique across all translation
+ // units in the linked program. The scheme fails if multiple translation
+ // units are compiled using the same relative source file path, or if
+ // multiple translation units are built from the same source file.
+ SourceManager &SM = getASTContext().getSourceManager();
+ Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]";
+ }
+
+ MicrosoftCXXNameMangler mangler(*this, Out);
+ mangler.mangleName(RD);
+}
+
MicrosoftMangleContext *
MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new MicrosoftMangleContextImpl(Context, Diags);
diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
index 3dc750a..a9b10ed 100644
--- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
@@ -27,7 +27,11 @@ IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
"NSMutableArray",
"NSDictionary",
"NSMutableDictionary",
- "NSNumber"
+ "NSNumber",
+ "NSMutableSet",
+ "NSCountedSet",
+ "NSMutableOrderedSet",
+ "NSValue"
};
if (!ClassIds[K])
@@ -124,6 +128,25 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
+ case NSMutableArr_addObject:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
+ break;
+ case NSMutableArr_insertObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("insertObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSMutableArr_setObjectAtIndexedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndexedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
}
return (NSArraySelectors[MK] = Sel);
}
@@ -209,6 +232,22 @@ Selector NSAPI::getNSDictionarySelector(
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
+ case NSMutableDict_setObjectForKeyedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("forKeyedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSMutableDict_setValueForKey: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setValue"),
+ &Ctx.Idents.get("forKey")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
}
return (NSDictionarySelectors[MK] = Sel);
}
@@ -227,6 +266,63 @@ NSAPI::getNSDictionaryMethodKind(Selector Sel) {
return None;
}
+Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
+ if (NSSetSelectors[MK].isNull()) {
+ Selector Sel;
+ switch (MK) {
+ case NSMutableSet_addObject:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
+ break;
+ case NSOrderedSet_insertObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("insertObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_setObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_setObjectAtIndexedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndexedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_replaceObjectAtIndexWithObject: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("replaceObjectAtIndex"),
+ &Ctx.Idents.get("withObject")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ }
+ return (NSSetSelectors[MK] = Sel);
+ }
+
+ return NSSetSelectors[MK];
+}
+
+Optional<NSAPI::NSSetMethodKind>
+NSAPI::getNSSetMethodKind(Selector Sel) {
+ for (unsigned i = 0; i != NumNSSetMethods; ++i) {
+ NSSetMethodKind MK = NSSetMethodKind(i);
+ if (Sel == getNSSetSelector(MK))
+ return MK;
+ }
+
+ return None;
+}
+
Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
bool Instance) const {
static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
@@ -410,6 +506,11 @@ StringRef NSAPI::GetNSIntegralKind(QualType T) const {
return StringRef();
}
+bool NSAPI::isMacroDefined(StringRef Id) const {
+ // FIXME: Check whether the relevant module macros are visible.
+ return Ctx.Idents.get(Id).hasMacroDefinition();
+}
+
bool NSAPI::isObjCTypedef(QualType T,
StringRef name, IdentifierInfo *&II) const {
if (!Ctx.getLangOpts().ObjC1)
diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
index a991302..d7d5f9c 100644
--- a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
@@ -36,8 +36,8 @@ static void BuildParentMap(MapTy& M, Stmt* S,
// If we are rebuilding the map, clear out any existing state.
if (M[POE->getSyntacticForm()])
- for (Stmt::child_range I = S->children(); I; ++I)
- M[*I] = nullptr;
+ for (Stmt *SubStmt : S->children())
+ M[SubStmt] = nullptr;
M[POE->getSyntacticForm()] = S;
BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
@@ -82,10 +82,10 @@ static void BuildParentMap(MapTy& M, Stmt* S,
break;
}
default:
- for (Stmt::child_range I = S->children(); I; ++I) {
- if (*I) {
- M[*I] = S;
- BuildParentMap(M, *I, OVMode);
+ for (Stmt *SubStmt : S->children()) {
+ if (SubStmt) {
+ M[SubStmt] = S;
+ BuildParentMap(M, SubStmt, OVMode);
}
}
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index 0d070a4..388c91c 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -55,6 +55,52 @@ struct BaseSubobjectInfo {
const BaseSubobjectInfo *Derived;
};
+/// \brief Externally provided layout. Typically used when the AST source, such
+/// as DWARF, lacks all the information that was available at compile time, such
+/// as alignment attributes on fields and pragmas in effect.
+struct ExternalLayout {
+ ExternalLayout() : Size(0), Align(0) {}
+
+ /// \brief Overall record size in bits.
+ uint64_t Size;
+
+ /// \brief Overall record alignment in bits.
+ uint64_t Align;
+
+ /// \brief Record field offsets in bits.
+ llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
+
+ /// \brief Direct, non-virtual base offsets.
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
+
+ /// \brief Virtual base offsets.
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
+
+ /// Get the offset of the given field. The external source must provide
+ /// entries for all fields in the record.
+ uint64_t getExternalFieldOffset(const FieldDecl *FD) {
+ assert(FieldOffsets.count(FD) &&
+ "Field does not have an external offset");
+ return FieldOffsets[FD];
+ }
+
+ bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
+ auto Known = BaseOffsets.find(RD);
+ if (Known == BaseOffsets.end())
+ return false;
+ BaseOffset = Known->second;
+ return true;
+ }
+
+ bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
+ auto Known = VirtualBaseOffsets.find(RD);
+ if (Known == VirtualBaseOffsets.end())
+ return false;
+ BaseOffset = Known->second;
+ return true;
+ }
+};
+
/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
/// offsets while laying out a C++ class.
class EmptySubobjectMap {
@@ -541,7 +587,7 @@ protected:
/// \brief Whether the external AST source has provided a layout for this
/// record.
- unsigned ExternalLayout : 1;
+ unsigned UseExternalLayout : 1;
/// \brief Whether we need to infer alignment, even when we have an
/// externally-provided layout.
@@ -607,26 +653,14 @@ protected:
/// avoid visiting virtual bases more than once.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
- /// \brief Externally-provided size.
- uint64_t ExternalSize;
-
- /// \brief Externally-provided alignment.
- uint64_t ExternalAlign;
-
- /// \brief Externally-provided field offsets.
- llvm::DenseMap<const FieldDecl *, uint64_t> ExternalFieldOffsets;
-
- /// \brief Externally-provided direct, non-virtual base offsets.
- llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalBaseOffsets;
-
- /// \brief Externally-provided virtual base offsets.
- llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalVirtualBaseOffsets;
+ /// Valid if UseExternalLayout is true.
+ ExternalLayout External;
RecordLayoutBuilder(const ASTContext &Context,
EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
- ExternalLayout(false), InferAlignment(false),
+ UseExternalLayout(false), InferAlignment(false),
Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
MaxFieldAlignment(CharUnits::Zero()),
@@ -748,8 +782,8 @@ protected:
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
- RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
- void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+ RecordLayoutBuilder(const RecordLayoutBuilder &) = delete;
+ void operator=(const RecordLayoutBuilder &) = delete;
};
} // end anonymous namespace
@@ -1134,21 +1168,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Query the external layout to see if it provides an offset.
bool HasExternalLayout = false;
- if (ExternalLayout) {
+ if (UseExternalLayout) {
llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known;
- if (Base->IsVirtual) {
- Known = ExternalVirtualBaseOffsets.find(Base->Class);
- if (Known != ExternalVirtualBaseOffsets.end()) {
- Offset = Known->second;
- HasExternalLayout = true;
- }
- } else {
- Known = ExternalBaseOffsets.find(Base->Class);
- if (Known != ExternalBaseOffsets.end()) {
- Offset = Known->second;
- HasExternalLayout = true;
- }
- }
+ if (Base->IsVirtual)
+ HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
+ else
+ HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
}
CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
@@ -1235,18 +1260,15 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
// If there is an external AST source, ask it for the various offsets.
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
- if (ExternalASTSource *External = Context.getExternalSource()) {
- ExternalLayout = External->layoutRecordType(RD,
- ExternalSize,
- ExternalAlign,
- ExternalFieldOffsets,
- ExternalBaseOffsets,
- ExternalVirtualBaseOffsets);
-
+ if (ExternalASTSource *Source = Context.getExternalSource()) {
+ UseExternalLayout = Source->layoutRecordType(
+ RD, External.Size, External.Align, External.FieldOffsets,
+ External.BaseOffsets, External.VirtualBaseOffsets);
+
// Update based on external alignment.
- if (ExternalLayout) {
- if (ExternalAlign > 0) {
- Alignment = Context.toCharUnitsFromBits(ExternalAlign);
+ if (UseExternalLayout) {
+ if (External.Align > 0) {
+ Alignment = Context.toCharUnitsFromBits(External.Align);
} else {
// The external source didn't have alignment information; infer it.
InferAlignment = true;
@@ -1445,7 +1467,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// ms_struct basically requests a complete replacement of the
// platform ABI's struct-layout algorithm, with the high-level goal
// of duplicating MSVC's layout. For non-bitfields, this follows
- // the the standard algorithm. The basic bitfield layout rule is to
+ // the standard algorithm. The basic bitfield layout rule is to
// allocate an entire unit of the bitfield's declared type
// (e.g. 'unsigned long'), then parcel it up among successive
// bitfields whose declared types have the same size, making a new
@@ -1588,7 +1610,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// If we're using external layout, give the external layout a chance
// to override this information.
- if (ExternalLayout)
+ if (UseExternalLayout)
FieldOffset = updateExternalFieldOffset(D, FieldOffset);
// Okay, place the bitfield at the calculated offset.
@@ -1604,7 +1626,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
FieldAlign = UnpackedFieldAlign = 1;
// Diagnose differences in layout due to padding or packing.
- if (!ExternalLayout)
+ if (!UseExternalLayout)
CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
UnpackedFieldAlign, FieldPacked, D);
@@ -1727,7 +1749,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
UnpackedFieldOffset =
UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign);
- if (ExternalLayout) {
+ if (UseExternalLayout) {
FieldOffset = Context.toCharUnitsFromBits(
updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
@@ -1750,7 +1772,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
// Place this field at the current location.
FieldOffsets.push_back(Context.toBits(FieldOffset));
- if (!ExternalLayout)
+ if (!UseExternalLayout)
CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
Context.toBits(UnpackedFieldOffset),
Context.toBits(UnpackedFieldAlign), FieldPacked, D);
@@ -1802,15 +1824,15 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
uint64_t RoundedSize
= llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment));
- if (ExternalLayout) {
+ if (UseExternalLayout) {
// If we're inferring alignment, and the external size is smaller than
// our size after we've rounded up to alignment, conservatively set the
// alignment to 1.
- if (InferAlignment && ExternalSize < RoundedSize) {
+ if (InferAlignment && External.Size < RoundedSize) {
Alignment = CharUnits::One();
InferAlignment = false;
}
- setSize(ExternalSize);
+ setSize(External.Size);
return;
}
@@ -1846,18 +1868,18 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
CharUnits UnpackedNewAlignment) {
// The alignment is not modified when using 'mac68k' alignment or when
// we have an externally-supplied layout that also provides overall alignment.
- if (IsMac68kAlign || (ExternalLayout && !InferAlignment))
+ if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
return;
if (NewAlignment > Alignment) {
- assert(llvm::isPowerOf2_32(NewAlignment.getQuantity() &&
- "Alignment not a power of 2"));
+ assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&
+ "Alignment not a power of 2");
Alignment = NewAlignment;
}
if (UnpackedNewAlignment > UnpackedAlignment) {
- assert(llvm::isPowerOf2_32(UnpackedNewAlignment.getQuantity() &&
- "Alignment not a power of 2"));
+ assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&
+ "Alignment not a power of 2");
UnpackedAlignment = UnpackedNewAlignment;
}
}
@@ -1865,11 +1887,8 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
uint64_t
RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
uint64_t ComputedOffset) {
- assert(ExternalFieldOffsets.find(Field) != ExternalFieldOffsets.end() &&
- "Field does not have an external offset");
-
- uint64_t ExternalFieldOffset = ExternalFieldOffsets[Field];
-
+ uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
+
if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
// The externally-supplied field offset is before the field offset we
// computed. Assume that the structure is packed.
@@ -2152,9 +2171,8 @@ struct MicrosoftRecordLayoutBuilder {
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {}
private:
- MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &)
- LLVM_DELETED_FUNCTION;
- void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+ MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;
+ void operator=(const MicrosoftRecordLayoutBuilder &) = delete;
public:
void layout(const RecordDecl *RD);
void cxxLayout(const CXXRecordDecl *RD);
@@ -2252,6 +2270,13 @@ public:
/// \brief True if this class is zero sized or first base is zero sized or
/// has this property. Only used for MS-ABI.
bool LeadsWithZeroSizedBase : 1;
+
+ /// \brief True if the external AST source provided a layout for this record.
+ bool UseExternalLayout : 1;
+
+ /// \brief The layout provided by the external AST source. Only active if
+ /// UseExternalLayout is true.
+ ExternalLayout External;
};
} // namespace
@@ -2354,8 +2379,9 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
// In 64-bit mode we always perform an alignment step after laying out vbases.
// In 32-bit mode we do not. The check to see if we need to perform alignment
// checks the RequiredAlignment field and performs alignment if it isn't 0.
- RequiredAlignment = Context.getTargetInfo().getPointerWidth(0) == 64 ?
- CharUnits::One() : CharUnits::Zero();
+ RequiredAlignment = Context.getTargetInfo().getTriple().isArch64Bit()
+ ? CharUnits::One()
+ : CharUnits::Zero();
// Compute the maximum field alignment.
MaxFieldAlignment = CharUnits::Zero();
// Honor the default struct packing maximum alignment flag.
@@ -2371,6 +2397,13 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
// Packed attribute forces max field alignment to be 1.
if (RD->hasAttr<PackedAttr>())
MaxFieldAlignment = CharUnits::One();
+
+ // Try to respect the external layout if present.
+ UseExternalLayout = false;
+ if (ExternalASTSource *Source = Context.getExternalSource())
+ UseExternalLayout = Source->layoutRecordType(
+ RD, External.Size, External.Align, External.FieldOffsets,
+ External.BaseOffsets, External.VirtualBaseOffsets);
}
void
@@ -2385,7 +2418,8 @@ MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
// injection.
PointerInfo.Size =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- PointerInfo.Alignment = PointerInfo.Size;
+ PointerInfo.Alignment =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
// Respect pragma pack.
if (!MaxFieldAlignment.isZero())
PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
@@ -2475,7 +2509,18 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
BaseLayout.leadsWithZeroSizedBase())
Size++;
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
- CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits BaseOffset;
+
+ // Respect the external AST source base offset, if present.
+ bool FoundBase = false;
+ if (UseExternalLayout) {
+ FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
+ if (FoundBase)
+ assert(BaseOffset >= Size && "base offset already allocated");
+ }
+
+ if (!FoundBase)
+ BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
Bases.insert(std::make_pair(BaseDecl, BaseOffset));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
PreviousBaseLayout = &BaseLayout;
@@ -2499,7 +2544,14 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
} else {
- CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits FieldOffset;
+ if (UseExternalLayout) {
+ FieldOffset =
+ Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
+ assert(FieldOffset >= Size && "field offset already allocated");
+ } else {
+ FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
+ }
placeFieldAtOffset(FieldOffset);
Size = FieldOffset + Info.Size;
}
@@ -2573,14 +2625,16 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
CharUnits InjectionSite = VBPtrOffset;
// But before we do, make sure it's properly aligned.
VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment);
+ // Shift everything after the vbptr down, unless we're using an external
+ // layout.
+ if (UseExternalLayout)
+ return;
// Determine where the first field should be laid out after the vbptr.
CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
// Make sure that the amount we push the fields back by is a multiple of the
// alignment.
CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(
std::max(RequiredAlignment, Alignment));
- // Increase the size of the object and push back all fields by the offset
- // amount.
Size += Offset;
for (uint64_t &FieldOffset : FieldOffsets)
FieldOffset += Context.toBits(Offset);
@@ -2647,7 +2701,18 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
}
// Insert the virtual base.
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
- CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits BaseOffset;
+
+ // Respect the external AST source base offset, if present.
+ bool FoundBase = false;
+ if (UseExternalLayout) {
+ FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
+ if (FoundBase)
+ assert(BaseOffset >= Size && "base offset already allocated");
+ }
+ if (!FoundBase)
+ BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
@@ -2677,6 +2742,12 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
else
Size = MinEmptyStructSize;
}
+
+ if (UseExternalLayout) {
+ Size = Context.toCharUnitsFromBits(External.Size);
+ if (External.Align)
+ Alignment = Context.toCharUnitsFromBits(External.Align);
+ }
}
// Recursively walks the non-virtual bases of a class and determines if any of
@@ -2815,7 +2886,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
const ASTRecordLayout *NewEntry = nullptr;
- if (isMsLayout(D) && !D->getASTContext().getExternalSource()) {
+ if (isMsLayout(D)) {
NewEntry = BuildMicrosoftASTRecordLayout(D);
} else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
EmptySubobjectMap EmptySubobjects(*this, RD);
@@ -2905,11 +2976,11 @@ void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) {
// Look up the cache entry. Since we're working with the first
// declaration, its parent must be the class definition, which is
// the correct key for the KeyFunctions hash.
- llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator
- I = KeyFunctions.find(Method->getParent());
+ const auto &Map = KeyFunctions;
+ auto I = Map.find(Method->getParent());
// If it's not cached, there's nothing to do.
- if (I == KeyFunctions.end()) return;
+ if (I == Map.end()) return;
// If it is cached, check whether it's the target method, and if so,
// remove it from the cache. Note, the call to 'get' might invalidate
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 68c7e72..c0aab4c 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -95,10 +95,16 @@ void Stmt::EnableStatistics() {
Stmt *Stmt::IgnoreImplicit() {
Stmt *s = this;
- if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s))
+ if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
s = ewc->getSubExpr();
- while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s))
+ if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
+ s = mte->GetTemporaryExpr();
+
+ if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
+ s = bte->getSubExpr();
+
+ while (auto *ice = dyn_cast<ImplicitCastExpr>(s))
s = ice->getSubExpr();
return s;
@@ -586,7 +592,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
SourceLocation EndLoc =
getAsmString()->getLocationOfByte(CurPtr - StrStart, SM, LO, TI);
- Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc));
+ Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
continue;
}
@@ -620,7 +626,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
SourceLocation EndLoc =
getAsmString()->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI);
- Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc));
+ Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
CurPtr = NameEnd+1;
continue;
@@ -934,8 +940,7 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
}
SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)
-{
+ : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
setConditionVariable(C, Var);
SubExprs[COND] = cond;
SubExprs[BODY] = nullptr;
@@ -1241,17 +1246,47 @@ OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPFirstprivateClause(N);
}
-OMPLastprivateClause *OMPLastprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
+ assert(PrivateCopies.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
+}
+
+void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
+}
+
+void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPLastprivateClause *OMPLastprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 5 * sizeof(Expr *) * VL.size());
OMPLastprivateClause *Clause =
new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1259,7 +1294,7 @@ OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 5 * sizeof(Expr *) * N);
return new (Mem) OMPLastprivateClause(N);
}
@@ -1285,27 +1320,56 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSharedClause(N);
}
-OMPLinearClause *OMPLinearClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL, Expr *Step) {
+void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
+ assert(IL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(IL.begin(), IL.end(), varlist_end());
+}
+
+void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
+ assert(UL.size() == varlist_size() &&
+ "Number of updates is not the same as the preallocated buffer");
+ std::copy(UL.begin(), UL.end(), getInits().end());
+}
+
+void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
+ assert(FL.size() == varlist_size() &&
+ "Number of final updates is not the same as the preallocated buffer");
+ std::copy(FL.begin(), FL.end(), getUpdates().end());
+}
+
+OMPLinearClause *
+OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (VL.size() + 1));
+ (4 * VL.size() + 2) * sizeof(Expr *));
OMPLinearClause *Clause = new (Mem)
OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setInits(IL);
+ // Fill update and final expressions with zeroes, they are provided later,
+ // after the directive construction.
+ std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
+ nullptr);
+ std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
+ nullptr);
Clause->setStep(Step);
+ Clause->setCalcStep(CalcStep);
return Clause;
}
OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
unsigned NumVars) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (NumVars + 1));
+ (4 * NumVars + 2) * sizeof(Expr *));
return new (Mem) OMPLinearClause(NumVars);
}
@@ -1331,17 +1395,41 @@ OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPAlignedClause(NumVars);
}
-OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyinClause *OMPCopyinClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1349,21 +1437,45 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPCopyinClause(N);
}
-OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyprivateClause *OMPCopyprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPCopyprivateClause *Clause =
new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1371,7 +1483,7 @@ OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPCopyprivateClause(N);
}
@@ -1399,16 +1511,42 @@ void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
std::copy(A.begin(), A.end(), getFinals().begin());
}
+void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end());
+}
+
+void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) {
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPReductionClause *Clause = new (Mem) OMPReductionClause(
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
return Clause;
}
@@ -1416,7 +1554,7 @@ OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPReductionClause(N);
}
@@ -1441,12 +1579,33 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPFlushClause(N);
}
+OMPDependClause *
+OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * VL.size());
+ OMPDependClause *Clause =
+ new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setDependencyKind(DepKind);
+ Clause->setDependencyLoc(DepLoc);
+ Clause->setColonLoc(ColonLoc);
+ return Clause;
+}
+
+OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * N);
+ return new (Mem) OMPDependClause(N);
+}
+
const OMPClause *
OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {
- auto ClauseFilter =
- [=](const OMPClause *C) -> bool { return C->getClauseKind() == K; };
- OMPExecutableDirective::filtered_clause_iterator<decltype(ClauseFilter)> I(
- clauses(), ClauseFilter);
+ auto &&I = getClausesOfKind(K);
if (I) {
auto *Clause = *I;
@@ -1501,7 +1660,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setLastIteration(Exprs.LastIteration);
Dir->setCalcLastIteration(Exprs.CalcLastIteration);
Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setCond(Exprs.Cond);
Dir->setInit(Exprs.Init);
Dir->setInc(Exprs.Inc);
Dir->setCounters(Exprs.Counters);
@@ -1540,7 +1699,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setLastIteration(Exprs.LastIteration);
Dir->setCalcLastIteration(Exprs.CalcLastIteration);
Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setCond(Exprs.Cond);
Dir->setInit(Exprs.Init);
Dir->setInc(Exprs.Inc);
Dir->setIsLastIterVariable(Exprs.IL);
@@ -1586,7 +1745,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setLastIteration(Exprs.LastIteration);
Dir->setCalcLastIteration(Exprs.CalcLastIteration);
Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setCond(Exprs.Cond);
Dir->setInit(Exprs.Init);
Dir->setInc(Exprs.Inc);
Dir->setIsLastIterVariable(Exprs.IL);
@@ -1642,7 +1801,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective),
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective),
llvm::alignOf<Stmt *>());
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
@@ -1741,7 +1900,7 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
Dir->setLastIteration(Exprs.LastIteration);
Dir->setCalcLastIteration(Exprs.CalcLastIteration);
Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setCond(Exprs.Cond);
Dir->setInit(Exprs.Init);
Dir->setInc(Exprs.Inc);
Dir->setIsLastIterVariable(Exprs.IL);
@@ -1785,7 +1944,7 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
Dir->setLastIteration(Exprs.LastIteration);
Dir->setCalcLastIteration(Exprs.CalcLastIteration);
Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setCond(Exprs.Cond);
Dir->setInit(Exprs.Init);
Dir->setInc(Exprs.Inc);
Dir->setIsLastIterVariable(Exprs.IL);
@@ -1906,6 +2065,67 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPTaskwaitDirective();
}
+OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ OMPTaskgroupDirective *Dir =
+ new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ return new (Mem) OMPTaskgroupDirective();
+}
+
+OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ unsigned Size = llvm::RoundUpToAlignment(
+ sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ OMPCancellationPointDirective *Dir =
+ new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
+ Dir->setCancelRegion(CancelRegion);
+ return Dir;
+}
+
+OMPCancellationPointDirective *
+OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(
+ sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ return new (Mem) OMPCancellationPointDirective();
+}
+
+OMPCancelDirective *
+OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc);
+ Dir->setCancelRegion(CancelRegion);
+ return Dir;
+}
+
+OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ return new (Mem) OMPCancelDirective();
+}
+
OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
@@ -1948,14 +2168,14 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPOrderedDirective();
}
-OMPAtomicDirective *
-OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E) {
+OMPAtomicDirective *OMPAtomicDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
llvm::alignOf<OMPClause *>());
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- 4 * sizeof(Stmt *));
+ 5 * sizeof(Stmt *));
OMPAtomicDirective *Dir =
new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -1963,6 +2183,9 @@ OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setX(X);
Dir->setV(V);
Dir->setExpr(E);
+ Dir->setUpdateExpr(UE);
+ Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
+ Dir->IsPostfixUpdate = IsPostfixUpdate;
return Dir;
}
@@ -1972,7 +2195,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
return new (Mem) OMPAtomicDirective(NumClauses);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
index 1ccba04..732756f 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
@@ -93,12 +93,12 @@ bool StmtIteratorBase::HandleDecl(Decl* D) {
}
StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
- : stmt(nullptr), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
+ : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
NextDecl(false);
}
StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
- : stmt(nullptr), DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) {
+ : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) {
RawVAPtr |= reinterpret_cast<uintptr_t>(t);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index 927a679..7960077 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -396,8 +396,9 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
}
VisitStringLiteral(Node->getOutputConstraintLiteral(i));
- OS << " ";
+ OS << " (";
Visit(Node->getOutputExpr(i));
+ OS << ")";
}
// Inputs
@@ -415,8 +416,9 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
}
VisitStringLiteral(Node->getInputConstraintLiteral(i));
- OS << " ";
+ OS << " (";
Visit(Node->getInputExpr(i));
+ OS << ")";
}
// Clobbers
@@ -797,6 +799,17 @@ void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
OS << ")";
}
}
+
+void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "depend(";
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ Node->getDependencyKind())
+ << " :";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
}
//===----------------------------------------------------------------------===//
@@ -908,6 +921,11 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) {
+ Indent() << "#pragma omp taskgroup";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
Indent() << "#pragma omp flush ";
PrintOMPExecutableDirective(Node);
@@ -933,6 +951,18 @@ void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPCancellationPointDirective(
+ OMPCancellationPointDirective *Node) {
+ Indent() << "#pragma omp cancellation point "
+ << getOpenMPDirectiveName(Node->getCancelRegion());
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
+ Indent() << "#pragma omp cancel "
+ << getOpenMPDirectiveName(Node->getCancelRegion());
+ PrintOMPExecutableDirective(Node);
+}
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -1069,7 +1099,8 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
// Emit suffixes. Integer literals are always a builtin integer type.
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
default: llvm_unreachable("Unexpected type for integer literal!");
- case BuiltinType::SChar: OS << "i8"; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U: OS << "i8"; break;
case BuiltinType::UChar: OS << "Ui8"; break;
case BuiltinType::Short: OS << "i16"; break;
case BuiltinType::UShort: OS << "Ui16"; break;
@@ -1198,6 +1229,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
case UETT_VecStep:
OS << "vec_step";
break;
+ case UETT_OpenMPRequiredSimdAlign:
+ OS << "__builtin_omp_required_simd_align";
+ break;
}
if (Node->isArgumentType()) {
OS << '(';
@@ -1373,34 +1407,37 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
return;
}
- OS << "{ ";
+ OS << "{";
for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
if (i) OS << ", ";
if (Node->getInit(i))
PrintExpr(Node->getInit(i));
else
- OS << "0";
+ OS << "{}";
}
- OS << " }";
+ OS << "}";
}
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
- OS << "( ";
+ OS << "(";
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
if (i) OS << ", ";
PrintExpr(Node->getExpr(i));
}
- OS << " )";
+ OS << ")";
}
void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
+ bool NeedsEquals = true;
for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(),
DEnd = Node->designators_end();
D != DEnd; ++D) {
if (D->isFieldDesignator()) {
if (D->getDotLoc().isInvalid()) {
- if (IdentifierInfo *II = D->getFieldName())
+ if (IdentifierInfo *II = D->getFieldName()) {
OS << II->getName() << ":";
+ NeedsEquals = false;
+ }
} else {
OS << "." << D->getFieldName()->getName();
}
@@ -1417,10 +1454,29 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
}
}
- OS << " = ";
+ if (NeedsEquals)
+ OS << " = ";
+ else
+ OS << " ";
PrintExpr(Node->getInit());
}
+void StmtPrinter::VisitDesignatedInitUpdateExpr(
+ DesignatedInitUpdateExpr *Node) {
+ OS << "{";
+ OS << "/*base*/";
+ PrintExpr(Node->getBase());
+ OS << ", ";
+
+ OS << "/*updater*/";
+ PrintExpr(Node->getUpdater());
+ OS << "}";
+}
+
+void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
+ OS << "/*no init*/";
+}
+
void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
if (Policy.LangOpts.CPlusPlus) {
OS << "/*implicit*/";
@@ -1621,6 +1677,15 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
const TemplateArgumentList *Args =
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
assert(Args);
+
+ if (Args->size() != 1) {
+ OS << "operator \"\" " << Node->getUDSuffix()->getName();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Args->data(), Args->size(), Policy);
+ OS << "()";
+ return;
+ }
+
const TemplateArgument &Pack = Args->get(0);
for (const auto &P : Pack.pack_elements()) {
char C = (char)P.getAsIntegral().getZExtValue();
@@ -1679,9 +1744,13 @@ void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
Node->getType().print(OS, Policy);
- OS << "(";
+ // If there are no parens, this is list-initialization, and the braces are
+ // part of the syntax of the inner construct.
+ if (Node->getLParenLoc().isValid())
+ OS << "(";
PrintExpr(Node->getSubExpr());
- OS << ")";
+ if (Node->getLParenLoc().isValid())
+ OS << ")";
}
void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
@@ -1690,7 +1759,12 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
Node->getType().print(OS, Policy);
- OS << "(";
+ if (Node->isStdInitListInitialization())
+ /* Nothing to do; braces are part of creating the std::initializer_list. */;
+ else if (Node->isListInitialization())
+ OS << "{";
+ else
+ OS << "(";
for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
ArgEnd = Node->arg_end();
Arg != ArgEnd; ++Arg) {
@@ -1700,7 +1774,12 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
OS << ", ";
PrintExpr(*Arg);
}
- OS << ")";
+ if (Node->isStdInitListInitialization())
+ /* See above. */;
+ else if (Node->isListInitialization())
+ OS << "}";
+ else
+ OS << ")";
}
void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
@@ -1734,7 +1813,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
break;
case LCK_ByRef:
- if (Node->getCaptureDefault() != LCD_ByRef || C->isInitCapture())
+ if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
OS << '&';
OS << C->getCapturedVar()->getName();
break;
@@ -1746,7 +1825,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
llvm_unreachable("VLA type in explicit captures.");
}
- if (C->isInitCapture())
+ if (Node->isInitCapture(C))
PrintExpr(C->getCapturedVar()->getInit());
}
OS << ']';
@@ -1866,8 +1945,8 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
}
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
- if (E->isListInitialization())
- OS << "{ ";
+ if (E->isListInitialization() && !E->isStdInitListInitialization())
+ OS << "{";
for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
if (isa<CXXDefaultArgExpr>(E->getArg(i))) {
@@ -1879,8 +1958,8 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
PrintExpr(E->getArg(i));
}
- if (E->isListInitialization())
- OS << " }";
+ if (E->isListInitialization() && !E->isStdInitListInitialization())
+ OS << "}";
}
void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index d1f25d6..da99692 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -69,9 +69,9 @@ namespace {
void StmtProfiler::VisitStmt(const Stmt *S) {
ID.AddInteger(S->getStmtClass());
- for (Stmt::const_child_range C = S->children(); C; ++C) {
- if (*C)
- Visit(*C);
+ for (const Stmt *SubStmt : S->children()) {
+ if (SubStmt)
+ Visit(SubStmt);
else
ID.AddInteger(0);
}
@@ -298,8 +298,12 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
- if (C->getChunkSize())
+ if (C->getChunkSize()) {
Profiler->VisitStmt(C->getChunkSize());
+ if (C->getHelperChunkSize()) {
+ Profiler->VisitStmt(C->getChunkSize());
+ }
+ }
}
void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {}
@@ -346,6 +350,15 @@ OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
void
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
@@ -356,10 +369,29 @@ void OMPClauseProfiler::VisitOMPReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
+ for (auto *E : C->lhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->inits()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->updates()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->finals()) {
+ Profiler->VisitStmt(E);
+ }
Profiler->VisitStmt(C->getStep());
+ Profiler->VisitStmt(C->getCalcStep());
}
void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
VisitOMPClauseList(C);
@@ -367,14 +399,35 @@ void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
}
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void
OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) {
+ VisitOMPClauseList(C);
+}
}
void
@@ -460,6 +513,10 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) {
VisitOMPExecutableDirective(S);
}
@@ -480,6 +537,15 @@ void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPCancellationPointDirective(
+ const OMPCancellationPointDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPCancelDirective(const OMPCancelDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -694,6 +760,18 @@ void StmtProfiler::VisitDesignatedInitExpr(const DesignatedInitExpr *S) {
}
}
+// Seems that if VisitInitListExpr() only works on the syntactic form of an
+// InitListExpr, then a DesignatedInitUpdateExpr is not encountered.
+void StmtProfiler::VisitDesignatedInitUpdateExpr(
+ const DesignatedInitUpdateExpr *S) {
+ llvm_unreachable("Unexpected DesignatedInitUpdateExpr in syntactic form of "
+ "initializer");
+}
+
+void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) {
+ llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer");
+}
+
void StmtProfiler::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *S) {
VisitExpr(S);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index e4f364d..cee5fee 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -170,15 +170,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
- : Type(Vector, canonType, vecType->isDependentType(),
- vecType->isInstantiationDependentType(),
- vecType->isVariablyModifiedType(),
- vecType->containsUnexpandedParameterPack()),
- ElementType(vecType)
-{
- VectorTypeBits.VecKind = vecKind;
- VectorTypeBits.NumElements = nElements;
-}
+ : VectorType(Vector, vecType, nElements, canonType, vecKind) {}
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
@@ -372,6 +364,11 @@ bool Type::isStructureType() const {
return RT->getDecl()->isStruct();
return false;
}
+bool Type::isObjCBoxableRecordType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->hasAttr<ObjCBoxableAttr>();
+ return false;
+}
bool Type::isInterfaceType() const {
if (const RecordType *RT = getAs<RecordType>())
return RT->getDecl()->isInterface();
@@ -469,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 {
@@ -517,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())
@@ -640,12 +1602,13 @@ bool Type::hasIntegerRepresentation() const {
bool Type::isIntegralType(ASTContext &Ctx) const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::Int128;
-
+ BT->getKind() <= BuiltinType::Int128;
+
+ // Complete enum types are integral in C.
if (!Ctx.getLangOpts().CPlusPlus)
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
- return ET->getDecl()->isComplete(); // Complete enum types are integral in C.
-
+ return ET->getDecl()->isComplete();
+
return false;
}
@@ -736,7 +1699,7 @@ bool Type::isSignedIntegerType() const {
bool Type::isSignedIntegerOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
- BT->getKind() <= BuiltinType::Int128;
+ BT->getKind() <= BuiltinType::Int128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
@@ -1089,7 +2052,7 @@ bool QualType::isTrivialType(ASTContext &Context) const {
bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
if ((*this)->isArrayType())
- return Context.getBaseElementType(*this).isTrivialType(Context);
+ return Context.getBaseElementType(*this).isTriviallyCopyableType(Context);
if (Context.getLangOpts().ObjCAutoRefCount) {
switch (getObjCLifetime()) {
@@ -1586,8 +2549,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86_64SysV: return "sysv_abi";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
- case CC_PnaclCall: return "pnaclcall";
case CC_IntelOclBicc: return "intel_ocl_bicc";
+ case CC_SpirFunction: return "spir_function";
+ case CC_SpirKernel: return "spir_kernel";
}
llvm_unreachable("Invalid calling convention.");
@@ -1720,7 +2684,7 @@ bool FunctionProtoType::isNothrow(const ASTContext &Ctx,
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
- if (EST == EST_Dynamic && ResultIfDependent == true) {
+ if (EST == EST_Dynamic && ResultIfDependent) {
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
for (unsigned I = 0, N = NumExceptions; I != N; ++I)
@@ -1925,7 +2889,12 @@ bool AttributedType::isCallingConv() const {
case attr_objc_gc:
case attr_objc_ownership:
case attr_noreturn:
- return false;
+ 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:
@@ -1936,7 +2905,6 @@ bool AttributedType::isCallingConv() const {
case attr_pascal:
case attr_ms_abi:
case attr_sysv_abi:
- case attr_pnaclcall:
case attr_inteloclbicc:
return true;
}
@@ -2075,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 {
@@ -2347,6 +3323,186 @@ LinkageInfo Type::getLinkageAndVisibility() const {
return LV;
}
+Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {
+ QualType type(this, 0);
+ do {
+ // Check whether this is an attributed type with nullability
+ // information.
+ if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {
+ if (auto nullability = attributed->getImmediateNullability())
+ return nullability;
+ }
+
+ // Desugar the type. If desugaring does nothing, we're done.
+ QualType desugared = type.getSingleStepDesugaredType(context);
+ if (desugared.getTypePtr() == type.getTypePtr())
+ return None;
+
+ type = desugared;
+ } while (true);
+}
+
+bool Type::canHaveNullability() const {
+ QualType type = getCanonicalTypeInternal();
+
+ switch (type->getTypeClass()) {
+ // We'll only see canonical types here.
+#define NON_CANONICAL_TYPE(Class, Parent) \
+ case Type::Class: \
+ llvm_unreachable("non-canonical type");
+#define TYPE(Class, Parent)
+#include "clang/AST/TypeNodes.def"
+
+ // Pointer types.
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::MemberPointer:
+ case Type::ObjCObjectPointer:
+ return true;
+
+ // Dependent types that could instantiate to pointer types.
+ case Type::UnresolvedUsing:
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::UnaryTransform:
+ case Type::TemplateTypeParm:
+ case Type::SubstTemplateTypeParmPack:
+ case Type::DependentName:
+ case Type::DependentTemplateSpecialization:
+ return true;
+
+ // Dependent template specializations can instantiate to pointer
+ // types unless they're known to be specializations of a class
+ // template.
+ case Type::TemplateSpecialization:
+ if (TemplateDecl *templateDecl
+ = cast<TemplateSpecializationType>(type.getTypePtr())
+ ->getTemplateName().getAsTemplateDecl()) {
+ if (isa<ClassTemplateDecl>(templateDecl))
+ return false;
+ }
+ return true;
+
+ // auto is considered dependent when it isn't deduced.
+ case Type::Auto:
+ return !cast<AutoType>(type.getTypePtr())->isDeduced();
+
+ case Type::Builtin:
+ switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
+ // Signed, unsigned, and floating-point types cannot have nullability.
+#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define BUILTIN_TYPE(Id, SingletonId)
+#include "clang/AST/BuiltinTypes.def"
+ return false;
+
+ // Dependent types that could instantiate to a pointer type.
+ case BuiltinType::Dependent:
+ case BuiltinType::Overload:
+ case BuiltinType::BoundMember:
+ case BuiltinType::PseudoObject:
+ case BuiltinType::UnknownAny:
+ case BuiltinType::ARCUnbridgedCast:
+ return true;
+
+ case BuiltinType::Void:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ case BuiltinType::OCLImage1d:
+ case BuiltinType::OCLImage1dArray:
+ case BuiltinType::OCLImage1dBuffer:
+ case BuiltinType::OCLImage2d:
+ case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage3d:
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::BuiltinFn:
+ case BuiltinType::NullPtr:
+ return false;
+ }
+
+ // Non-pointer types.
+ case Type::Complex:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Record:
+ case Type::Enum:
+ case Type::InjectedClassName:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::Atomic:
+ return false;
+ }
+ llvm_unreachable("bad type kind!");
+}
+
+llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const {
+ if (getAttrKind() == AttributedType::attr_nonnull)
+ return NullabilityKind::NonNull;
+ if (getAttrKind() == AttributedType::attr_nullable)
+ return NullabilityKind::Nullable;
+ if (getAttrKind() == AttributedType::attr_null_unspecified)
+ return NullabilityKind::Unspecified;
+ return None;
+}
+
+Optional<NullabilityKind> AttributedType::stripOuterNullability(QualType &T) {
+ if (auto attributed = dyn_cast<AttributedType>(T.getTypePtr())) {
+ if (auto nullability = attributed->getImmediateNullability()) {
+ T = attributed->getModifiedType();
+ return nullability;
+ }
+ }
+
+ 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;
@@ -2378,6 +3534,11 @@ bool Type::isObjCNSObjectType() const {
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
return false;
}
+bool Type::isObjCIndependentClassType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
+ return false;
+}
bool Type::isObjCRetainableType() const {
return isObjCObjectPointerType() ||
isBlockPointerType() ||
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
index c069eb0..85bda6a 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index e36fc17..0bb50c6 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -110,7 +110,7 @@ namespace {
};
}
-static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) {
+static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) {
bool appendSpace = false;
if (TypeQuals & Qualifiers::Const) {
OS << "const";
@@ -123,7 +123,11 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) {
}
if (TypeQuals & Qualifiers::Restrict) {
if (appendSpace) OS << ' ';
- OS << "restrict";
+ if (C99) {
+ OS << "restrict";
+ } else {
+ OS << "__restrict";
+ }
}
}
@@ -432,7 +436,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers());
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
OS << ' ';
}
@@ -465,7 +469,7 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers());
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
OS << ' ';
}
@@ -685,9 +689,6 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_AAPCS_VFP:
OS << " __attribute__((pcs(\"aapcs-vfp\")))";
break;
- case CC_PnaclCall:
- OS << " __attribute__((pnaclcall))";
- break;
case CC_IntelOclBicc:
OS << " __attribute__((intel_ocl_bicc))";
break;
@@ -697,6 +698,10 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_X86_64SysV:
OS << " __attribute__((sysv_abi))";
break;
+ case CC_SpirFunction:
+ case CC_SpirKernel:
+ // Do nothing. These CCs are not available as attributes.
+ break;
}
}
@@ -708,7 +713,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
if (unsigned quals = T->getTypeQuals()) {
OS << ' ';
- AppendTypeQualList(OS, quals);
+ AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
}
switch (T->getRefQualifier()) {
@@ -1124,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()) {
@@ -1136,6 +1144,21 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
}
spaceBeforePlaceHolder(OS);
}
+
+ // Print nullability type specifiers.
+ if (T->getAttrKind() == AttributedType::attr_nonnull ||
+ T->getAttrKind() == AttributedType::attr_nullable ||
+ T->getAttrKind() == AttributedType::attr_null_unspecified) {
+ if (T->getAttrKind() == AttributedType::attr_nonnull)
+ OS << " _Nonnull";
+ else if (T->getAttrKind() == AttributedType::attr_nullable)
+ OS << " _Nullable";
+ else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
+ OS << " _Null_unspecified";
+ else
+ llvm_unreachable("unhandled nullability");
+ spaceBeforePlaceHolder(OS);
+ }
}
void TypePrinter::printAttributedAfter(const AttributedType *T,
@@ -1145,16 +1168,41 @@ 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;
+ // Nothing to print after.
+ if (T->getAttrKind() == AttributedType::attr_nonnull ||
+ T->getAttrKind() == AttributedType::attr_nullable ||
+ T->getAttrKind() == AttributedType::attr_null_unspecified)
+ return printAfter(T->getModifiedType(), OS);
+
// If this is a calling convention attribute, don't print the implicit CC from
// the modified type.
SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
printAfter(T->getModifiedType(), OS);
+ // Print nullability type specifiers that occur after
+ if (T->getAttrKind() == AttributedType::attr_nonnull ||
+ T->getAttrKind() == AttributedType::attr_nullable ||
+ T->getAttrKind() == AttributedType::attr_null_unspecified) {
+ if (T->getAttrKind() == AttributedType::attr_nonnull)
+ OS << " _Nonnull";
+ else if (T->getAttrKind() == AttributedType::attr_nullable)
+ OS << " _Nullable";
+ else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
+ OS << " _Null_unspecified";
+ else
+ llvm_unreachable("unhandled nullability");
+
+ return;
+ }
+
OS << " __attribute__((";
switch (T->getAttrKind()) {
default: llvm_unreachable("This attribute should have been handled already");
@@ -1253,7 +1301,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
}
- case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break;
case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
}
OS << "))";
@@ -1269,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,
@@ -1473,7 +1522,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
unsigned quals = getCVRQualifiers();
if (quals) {
- AppendTypeQualList(OS, quals);
+ AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
addSpace = true;
}
if (unsigned addrspace = getAddressSpace()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
index ddb1f05..ca5f0aa 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
@@ -13,9 +13,11 @@
#include "clang/AST/VTableBuilder.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -216,7 +218,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
#endif
}
-static BaseOffset ComputeBaseOffset(ASTContext &Context,
+static BaseOffset ComputeBaseOffset(const ASTContext &Context,
const CXXRecordDecl *DerivedRD,
const CXXBasePath &Path) {
CharUnits NonVirtualOffset = CharUnits::Zero();
@@ -255,7 +257,7 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context,
}
-static BaseOffset ComputeBaseOffset(ASTContext &Context,
+static BaseOffset ComputeBaseOffset(const ASTContext &Context,
const CXXRecordDecl *BaseRD,
const CXXRecordDecl *DerivedRD) {
CXXBasePaths Paths(/*FindAmbiguities=*/false,
@@ -411,7 +413,8 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
-
+ MD = MD->getCanonicalDecl();
+
OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
Out << " ";
@@ -695,6 +698,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
CharUnits OffsetOffset = getCurrentOffsetOffset();
@@ -1514,6 +1518,7 @@ void ItaniumVTableBuilder::AddMethods(
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
// Get the final overrider.
FinalOverriders::OverriderInfo Overrider =
@@ -2196,6 +2201,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// We only want virtual member functions.
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
std::string MethodName =
PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
@@ -2585,7 +2591,9 @@ public:
// Only include the RTTI component if we know that we will provide a
// definition of the vftable.
HasRTTIComponent = Context.getLangOpts().RTTIData &&
- !MostDerivedClass->hasAttr<DLLImportAttr>();
+ !MostDerivedClass->hasAttr<DLLImportAttr>() &&
+ MostDerivedClass->getTemplateSpecializationKind() !=
+ TSK_ExplicitInstantiationDeclaration;
LayoutVFTable();
@@ -2625,8 +2633,6 @@ public:
void dumpLayout(raw_ostream &);
};
-} // end namespace
-
/// InitialOverriddenDefinitionCollector - Finds the set of least derived bases
/// that define the given method.
struct InitialOverriddenDefinitionCollector {
@@ -2641,6 +2647,8 @@ struct InitialOverriddenDefinitionCollector {
}
};
+} // end namespace
+
static bool BaseInSet(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, void *BasesSet) {
BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
@@ -2730,8 +2738,9 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
CharUnits ThisOffset = Overrider.Offset;
CharUnits LastVBaseOffset;
- // For each path from the overrider to the parents of the overridden methods,
- // traverse the path, calculating the this offset in the most derived class.
+ // For each path from the overrider to the parents of the overridden
+ // methods, traverse the path, calculating the this offset in the most
+ // derived class.
for (int J = 0, F = Path.size(); J != F; ++J) {
const CXXBasePathElement &Element = Path[J];
QualType CurTy = Element.Base->getType();
@@ -2930,6 +2939,7 @@ static void GroupNewVirtualOverloads(
typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
VisitedGroupIndicesTy VisitedGroupIndices;
for (const auto *MD : RD->methods()) {
+ MD = MD->getCanonicalDecl();
VisitedGroupIndicesTy::iterator J;
bool Inserted;
std::tie(J, Inserted) = VisitedGroupIndices.insert(
@@ -2962,7 +2972,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
// See if this class expands a vftable of the base we look at, which is either
- // the one defined by the vfptr base path or the primary base of the current class.
+ // the one defined by the vfptr base path or the primary base of the current
+ // class.
const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
CharUnits NextBaseOffset;
if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
@@ -3020,7 +3031,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
ThisAdjustmentOffset);
if (OverriddenMD) {
- // If MD overrides anything in this vftable, we need to update the entries.
+ // If MD overrides anything in this vftable, we need to update the
+ // entries.
MethodInfoMapTy::iterator OverriddenMDIterator =
MethodInfoMap.find(OverriddenMD);
@@ -3435,55 +3447,176 @@ MicrosoftVTableContext::~MicrosoftVTableContext() {
llvm::DeleteContainerSeconds(VBaseInfo);
}
-static bool
-findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
- const CXXRecordDecl *RD, CharUnits Offset,
- llvm::SmallPtrSetImpl<const CXXRecordDecl *> &VBasesSeen,
- VPtrInfo::BasePath &FullPath, VPtrInfo *Info) {
- if (RD == Info->BaseWithVPtr && Offset == Info->FullOffsetInMDC) {
- Info->PathToBaseWithVPtr = FullPath;
- return true;
+namespace {
+typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
+ llvm::DenseSet<BaseSubobject>> FullPathTy;
+}
+
+// This recursive function finds all paths from a subobject centered at
+// (RD, Offset) to the subobject located at BaseWithVPtr.
+static void findPathsToSubobject(ASTContext &Context,
+ const ASTRecordLayout &MostDerivedLayout,
+ const CXXRecordDecl *RD, CharUnits Offset,
+ BaseSubobject BaseWithVPtr,
+ FullPathTy &FullPath,
+ std::list<FullPathTy> &Paths) {
+ if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
+ Paths.push_back(FullPath);
+ return;
}
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- // Recurse with non-virtual bases first.
- // FIXME: Does this need to be in layout order? Virtual bases will be in base
- // specifier order, which isn't necessarily layout order.
- SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end());
- std::stable_partition(Bases.begin(), Bases.end(),
- [](CXXBaseSpecifier bs) { return !bs.isVirtual(); });
-
- for (const auto &B : Bases) {
- const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
- CharUnits NewOffset;
- if (!B.isVirtual())
- NewOffset = Offset + Layout.getBaseClassOffset(Base);
- else {
- if (!VBasesSeen.insert(Base).second)
- return false;
- NewOffset = MostDerivedLayout.getVBaseClassOffset(Base);
- }
- FullPath.push_back(Base);
- if (findPathForVPtr(Context, MostDerivedLayout, Base, NewOffset, VBasesSeen,
- FullPath, Info))
- return true;
+ for (const CXXBaseSpecifier &BS : RD->bases()) {
+ const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
+ CharUnits NewOffset = BS.isVirtual()
+ ? MostDerivedLayout.getVBaseClassOffset(Base)
+ : Offset + Layout.getBaseClassOffset(Base);
+ FullPath.insert(BaseSubobject(Base, NewOffset));
+ findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
+ BaseWithVPtr, FullPath, Paths);
FullPath.pop_back();
}
- return false;
+}
+
+// Return the paths which are not subsets of other paths.
+static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
+ FullPaths.remove_if([&](const FullPathTy &SpecificPath) {
+ for (const FullPathTy &OtherPath : FullPaths) {
+ if (&SpecificPath == &OtherPath)
+ continue;
+ if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
+ [&](const BaseSubobject &BSO) {
+ return OtherPath.count(BSO) != 0;
+ })) {
+ return true;
+ }
+ }
+ return false;
+ });
+}
+
+static CharUnits getOffsetOfFullPath(ASTContext &Context,
+ const CXXRecordDecl *RD,
+ const FullPathTy &FullPath) {
+ const ASTRecordLayout &MostDerivedLayout =
+ Context.getASTRecordLayout(RD);
+ CharUnits Offset = CharUnits::fromQuantity(-1);
+ for (const BaseSubobject &BSO : FullPath) {
+ const CXXRecordDecl *Base = BSO.getBase();
+ // The first entry in the path is always the most derived record, skip it.
+ if (Base == RD) {
+ assert(Offset.getQuantity() == -1);
+ Offset = CharUnits::Zero();
+ continue;
+ }
+ assert(Offset.getQuantity() != -1);
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ // While we know which base has to be traversed, we don't know if that base
+ // was a virtual base.
+ const CXXBaseSpecifier *BaseBS = std::find_if(
+ RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) {
+ return BS.getType()->getAsCXXRecordDecl() == Base;
+ });
+ Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base)
+ : Offset + Layout.getBaseClassOffset(Base);
+ RD = Base;
+ }
+ return Offset;
+}
+
+// We want to select the path which introduces the most covariant overrides. If
+// two paths introduce overrides which the other path doesn't contain, issue a
+// diagnostic.
+static const FullPathTy *selectBestPath(ASTContext &Context,
+ const CXXRecordDecl *RD, VPtrInfo *Info,
+ std::list<FullPathTy> &FullPaths) {
+ // Handle some easy cases first.
+ if (FullPaths.empty())
+ return nullptr;
+ if (FullPaths.size() == 1)
+ return &FullPaths.front();
+
+ const FullPathTy *BestPath = nullptr;
+ typedef std::set<const CXXMethodDecl *> OverriderSetTy;
+ OverriderSetTy LastOverrides;
+ for (const FullPathTy &SpecificPath : FullPaths) {
+ assert(!SpecificPath.empty());
+ OverriderSetTy CurrentOverrides;
+ const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
+ // Find the distance from the start of the path to the subobject with the
+ // VPtr.
+ CharUnits BaseOffset =
+ getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
+ FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
+ for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
+ if (!MD->isVirtual())
+ continue;
+ FinalOverriders::OverriderInfo OI =
+ Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
+ const CXXMethodDecl *OverridingMethod = OI.Method;
+ // Only overriders which have a return adjustment introduce problematic
+ // thunks.
+ if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
+ .isEmpty())
+ continue;
+ // It's possible that the overrider isn't in this path. If so, skip it
+ // because this path didn't introduce it.
+ const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
+ if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
+ [&](const BaseSubobject &BSO) {
+ return BSO.getBase() == OverridingParent;
+ }))
+ continue;
+ CurrentOverrides.insert(OverridingMethod);
+ }
+ OverriderSetTy NewOverrides =
+ llvm::set_difference(CurrentOverrides, LastOverrides);
+ if (NewOverrides.empty())
+ continue;
+ OverriderSetTy MissingOverrides =
+ llvm::set_difference(LastOverrides, CurrentOverrides);
+ if (MissingOverrides.empty()) {
+ // This path is a strict improvement over the last path, let's use it.
+ BestPath = &SpecificPath;
+ std::swap(CurrentOverrides, LastOverrides);
+ } else {
+ // This path introduces an overrider with a conflicting covariant thunk.
+ DiagnosticsEngine &Diags = Context.getDiagnostics();
+ const CXXMethodDecl *CovariantMD = *NewOverrides.begin();
+ const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
+ Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
+ << RD;
+ Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
+ << CovariantMD;
+ Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
+ << ConflictMD;
+ }
+ }
+ // Go with the path that introduced the most covariant overrides. If there is
+ // no such path, pick the first path.
+ return BestPath ? BestPath : &FullPaths.front();
}
static void computeFullPathsForVFTables(ASTContext &Context,
const CXXRecordDecl *RD,
VPtrInfoVector &Paths) {
- llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
- VPtrInfo::BasePath FullPath;
+ FullPathTy FullPath;
+ std::list<FullPathTy> FullPaths;
for (VPtrInfo *Info : Paths) {
- findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(),
- VBasesSeen, FullPath, Info);
- VBasesSeen.clear();
+ findPathsToSubobject(
+ Context, MostDerivedLayout, RD, CharUnits::Zero(),
+ BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
+ FullPaths);
FullPath.clear();
+ removeRedundantPaths(FullPaths);
+ Info->PathToBaseWithVPtr.clear();
+ if (const FullPathTy *BestPath =
+ selectBestPath(Context, RD, Info, FullPaths))
+ for (const BaseSubobject &BSO : *BestPath)
+ Info->PathToBaseWithVPtr.push_back(BSO.getBase());
+ FullPaths.clear();
}
}
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index fa7968a..e3b666e 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -300,7 +300,7 @@ public:
const MatchFinder::MatchFinderOptions &Options)
: Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
- ~MatchASTVisitor() {
+ ~MatchASTVisitor() override {
if (Options.CheckProfiling) {
Options.CheckProfiling->Records = std::move(TimeByBucket);
}
@@ -912,37 +912,37 @@ MatchFinder::~MatchFinder() {}
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.DeclOrStmt.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.Type.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.Type.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.DeclOrStmt.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.NestedNameSpecifier.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.NestedNameSpecifierLoc.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.TypeLoc.push_back(std::make_pair(NodeMatch, Action));
+ Matchers.TypeLoc.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.push_back(Action);
}
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 2c482e3..069fcba 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/contrib/llvm/tools/clang/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>
@@ -114,9 +114,9 @@ DynTypedMatcher DynTypedMatcher::constructVariadic(
assert(InnerMatchers.size() > 0 && "Array must not be empty.");
assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
[&InnerMatchers](const DynTypedMatcher &M) {
- return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
+ return InnerMatchers[0].canConvertTo(M.SupportedKind);
}) &&
- "SupportedKind must match!");
+ "SupportedKind must be convertible to a common type!");
auto SupportedKind = InnerMatchers[0].SupportedKind;
// We must relax the restrict kind here.
@@ -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/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
index b0abdc7..72f1271 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -12,10 +12,9 @@
namespace clang {
namespace ast_matchers {
namespace dynamic {
-
Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
SourceRange Range) {
- ContextStack.push_back(ContextFrame());
+ ContextStack.emplace_back();
ContextFrame& data = ContextStack.back();
data.Type = Type;
data.Range = Range;
@@ -66,16 +65,16 @@ Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
ErrorType Error) {
- Errors.push_back(ErrorContent());
+ Errors.emplace_back();
ErrorContent &Last = Errors.back();
Last.ContextStack = ContextStack;
- Last.Messages.push_back(ErrorContent::Message());
+ Last.Messages.emplace_back();
Last.Messages.back().Range = Range;
Last.Messages.back().Type = Error;
return ArgStream(&Last.Messages.back().Args);
}
-StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
+static StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
switch (Type) {
case Diagnostics::CT_MatcherConstruct:
return "Error building matcher $0.";
@@ -85,7 +84,7 @@ StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
llvm_unreachable("Unknown ContextType value.");
}
-StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
+static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
switch (Type) {
case Diagnostics::ET_RegistryMatcherNotFound:
return "Matcher not found: $0";
@@ -130,8 +129,9 @@ StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
llvm_unreachable("Unknown ErrorType value.");
}
-void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
- llvm::raw_ostream &OS) {
+static void formatErrorString(StringRef FormatString,
+ ArrayRef<std::string> Args,
+ llvm::raw_ostream &OS) {
while (!FormatString.empty()) {
std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
OS << Pieces.first.str();
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index b78bc03..36a6415 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -181,18 +181,20 @@ public:
ArgKinds(ArgKinds.begin(), ArgKinds.end()) {}
VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
return Marshaller(Func, MatcherName, NameRange, Args, Error);
}
- bool isVariadic() const { return false; }
- unsigned getNumArgs() const { return ArgKinds.size(); }
+ bool isVariadic() const override { return false; }
+ unsigned getNumArgs() const override { return ArgKinds.size(); }
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgKinds[ArgNo]);
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
return isRetKindConvertibleTo(RetKinds, Kind, Specificity,
LeastDerivedKind);
}
@@ -333,18 +335,20 @@ public:
}
VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
return Func(MatcherName, NameRange, Args, Error);
}
- bool isVariadic() const { return true; }
- unsigned getNumArgs() const { return 0; }
+ bool isVariadic() const override { return true; }
+ unsigned getNumArgs() const override { return 0; }
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgsKind);
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
return isRetKindConvertibleTo(RetKinds, Kind, Specificity,
LeastDerivedKind);
}
@@ -487,11 +491,11 @@ public:
OverloadedMatcherDescriptor(ArrayRef<MatcherDescriptor *> Callbacks)
: Overloads(Callbacks.begin(), Callbacks.end()) {}
- virtual ~OverloadedMatcherDescriptor() {}
+ ~OverloadedMatcherDescriptor() override {}
- virtual VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) const {
+ VariantMatcher create(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
std::vector<VariantMatcher> Constructed;
Diagnostics::OverloadContext Ctx(Error);
for (const auto &O : Overloads) {
@@ -512,7 +516,7 @@ public:
return Constructed[0];
}
- bool isVariadic() const {
+ bool isVariadic() const override {
bool Overload0Variadic = Overloads[0]->isVariadic();
#ifndef NDEBUG
for (const auto &O : Overloads) {
@@ -522,7 +526,7 @@ public:
return Overload0Variadic;
}
- unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
unsigned Overload0NumArgs = Overloads[0]->getNumArgs();
#ifndef NDEBUG
for (const auto &O : Overloads) {
@@ -533,15 +537,16 @@ public:
}
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
- std::vector<ArgKind> &Kinds) const {
+ std::vector<ArgKind> &Kinds) const override {
for (const auto &O : Overloads) {
if (O->isConvertibleTo(ThisKind))
O->getArgKinds(ThisKind, ArgNo, Kinds);
}
}
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
- ast_type_traits::ASTNodeKind *LeastDerivedKind) const {
+ bool isConvertibleTo(
+ ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
+ ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
for (const auto &O : Overloads) {
if (O->isConvertibleTo(Kind, Specificity, LeastDerivedKind))
return true;
@@ -562,9 +567,9 @@ public:
: MinCount(MinCount), MaxCount(MaxCount), Op(Op),
MatcherName(MatcherName) {}
- virtual VariantMatcher create(const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) const override {
+ VariantMatcher create(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const override {
if (Args.size() < MinCount || MaxCount < Args.size()) {
const std::string MaxStr =
(MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str();
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index 9930c53..96a78cd 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index d550a89..72713dd 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -128,6 +128,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(constructorDecl);
REGISTER_MATCHER(containsDeclaration);
REGISTER_MATCHER(continueStmt);
+ REGISTER_MATCHER(conversionDecl);
REGISTER_MATCHER(cStyleCastExpr);
REGISTER_MATCHER(ctorInitializer);
REGISTER_MATCHER(CUDAKernelCallExpr);
@@ -198,6 +199,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasIncrement);
REGISTER_MATCHER(hasIndex);
REGISTER_MATCHER(hasInitializer);
+ REGISTER_MATCHER(hasKeywordSelector);
REGISTER_MATCHER(hasLHS);
REGISTER_MATCHER(hasLocalQualifiers);
REGISTER_MATCHER(hasLocalStorage);
@@ -205,6 +207,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasLoopVariable);
REGISTER_MATCHER(hasMethod);
REGISTER_MATCHER(hasName);
+ REGISTER_MATCHER(hasNullSelector);
REGISTER_MATCHER(hasObjectExpression);
REGISTER_MATCHER(hasOperatorName);
REGISTER_MATCHER(hasOverloadedOperatorName);
@@ -212,7 +215,9 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasParent);
REGISTER_MATCHER(hasQualifier);
REGISTER_MATCHER(hasRangeInit);
+ REGISTER_MATCHER(hasReceiverType);
REGISTER_MATCHER(hasRHS);
+ REGISTER_MATCHER(hasSelector);
REGISTER_MATCHER(hasSingleDecl);
REGISTER_MATCHER(hasSize);
REGISTER_MATCHER(hasSizeExpr);
@@ -223,6 +228,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTrueExpression);
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
+ REGISTER_MATCHER(hasUnarySelector);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
REGISTER_MATCHER(ignoringImpCasts);
@@ -234,6 +240,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isCatchAll);
REGISTER_MATCHER(isConst);
REGISTER_MATCHER(isConstQualified);
REGISTER_MATCHER(isDefinition);
@@ -262,6 +269,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(lambdaExpr);
REGISTER_MATCHER(lValueReferenceType);
REGISTER_MATCHER(matchesName);
+ REGISTER_MATCHER(matchesSelector);
REGISTER_MATCHER(materializeTemporaryExpr);
REGISTER_MATCHER(member);
REGISTER_MATCHER(memberCallExpr);
@@ -276,7 +284,9 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(newExpr);
REGISTER_MATCHER(nullPtrLiteralExpr);
REGISTER_MATCHER(nullStmt);
+ REGISTER_MATCHER(numSelectorArgs);
REGISTER_MATCHER(ofClass);
+ REGISTER_MATCHER(objcMessageExpr);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
REGISTER_MATCHER(operatorCallExpr);
@@ -302,6 +312,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(specifiesTypeLoc);
REGISTER_MATCHER(statementCountIs);
REGISTER_MATCHER(staticCastExpr);
+ REGISTER_MATCHER(staticAssertDecl);
REGISTER_MATCHER(stmt);
REGISTER_MATCHER(stringLiteral);
REGISTER_MATCHER(substNonTypeTemplateParmExpr);
@@ -315,6 +326,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(throughUsingDecl);
REGISTER_MATCHER(throwExpr);
REGISTER_MATCHER(to);
+ REGISTER_MATCHER(translationUnitDecl);
REGISTER_MATCHER(tryStmt);
REGISTER_MATCHER(type);
REGISTER_MATCHER(typedefDecl);
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index a88b707..9d8be47 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
index be66f32..d7fb7e9 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -472,9 +472,9 @@ public:
: BEVals(bevals), BC(bc) {}
void VisitStmt(Stmt *S) {
- for (Stmt::child_range I = S->children(); I; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
void VisitDeclRefExpr(DeclRefExpr *DR) {
@@ -530,14 +530,14 @@ static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
return BV;
}
-std::pair<AnalysisDeclContext::referenced_decls_iterator,
- AnalysisDeclContext::referenced_decls_iterator>
+llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
if (!ReferencedBlockVars)
ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
- DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
- return std::make_pair(V->begin(), V->end());
+ const DeclVec *V =
+ LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
+ return llvm::make_range(V->begin(), V->end());
}
ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index d9073aa..54d15bd 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -156,7 +156,7 @@ public:
return !(*this == rhs);
}
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return *this != const_iterator();
}
@@ -203,9 +203,9 @@ int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
return D;
}
-/// BlockScopePosPair - Structure for specifying position in CFG during its
-/// build process. It consists of CFGBlock that specifies position in CFG graph
-/// and LocalScope::const_iterator that specifies position in LocalScope graph.
+/// Structure for specifying position in CFG during its build process. It
+/// consists of CFGBlock that specifies position in CFG and
+/// LocalScope::const_iterator that specifies position in LocalScope graph.
struct BlockScopePosPair {
BlockScopePosPair() : block(nullptr) {}
BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
@@ -270,9 +270,8 @@ reverse_children::reverse_children(Stmt *S) {
}
// Default case for all other statements.
- for (Stmt::child_range I = S->children(); I; ++I) {
- childrenBuf.push_back(*I);
- }
+ for (Stmt *SubStmt : S->children())
+ childrenBuf.push_back(SubStmt);
// This needs to be done *after* childrenBuf has been populated.
children = childrenBuf;
@@ -454,7 +453,7 @@ private:
TerminatorExpr(nullptr) {}
/// Returns whether we need to start a new branch for a temporary destructor
- /// call. This is the case when the the temporary destructor is
+ /// call. This is the case when the temporary destructor is
/// conditionally executed, and it is the first one we encounter while
/// visiting a subexpression - other temporary destructors at the same level
/// will be added to the same block and are executed under the same
@@ -841,12 +840,12 @@ private:
// must be false.
llvm::APSInt IntVal;
if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
- if (IntVal.getBoolValue() == false) {
+ if (!IntVal.getBoolValue()) {
return TryResult(false);
}
}
if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
- if (IntVal.getBoolValue() == false) {
+ if (!IntVal.getBoolValue()) {
return TryResult(false);
}
}
@@ -1095,6 +1094,19 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
// generating destructors for the second time.
return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
}
+ if (BuildOpts.AddCXXDefaultInitExprInCtors) {
+ if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) {
+ // In general, appending the expression wrapped by a CXXDefaultInitExpr
+ // may cause the same Expr to appear more than once in the CFG. Doing it
+ // here is safe because there's only one initializer per field.
+ autoCreateBlock();
+ appendStmt(Block, Default);
+ if (Stmt *Child = Default->getExpr())
+ if (CFGBlock *R = Visit(Child))
+ Block = R;
+ return Block;
+ }
+ }
return Visit(Init);
}
@@ -1179,8 +1191,7 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
}
Ty = Context->getBaseElementType(Ty);
- const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
- if (Dtor->isNoReturn())
+ if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();
@@ -3629,11 +3640,11 @@ CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
// bottom-up, this means we visit them in their natural order, which
// reverses them in the CFG.
CFGBlock *B = Block;
- for (Stmt::child_range I = E->children(); I; ++I) {
- if (Stmt *Child = *I)
+ for (Stmt *Child : E->children())
+ if (Child)
if (CFGBlock *R = VisitForTemporaryDtors(Child, false, Context))
B = R;
- }
+
return B;
}
@@ -3682,7 +3693,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
- if (Dtor->isNoReturn()) {
+ if (Dtor->getParent()->isAnyDestructorNoReturn()) {
// If the destructor is marked as a no-return destructor, we need to
// create a new block for the destructor which does not have as a
// successor anything built thus far. Control won't flow out of this
@@ -3950,9 +3961,8 @@ public:
}
}
}
-
- virtual ~StmtPrinterHelper() {}
+ ~StmtPrinterHelper() override {}
const LangOptions &getLangOpts() const { return LangOpts; }
void setBlockID(signed i) { currentBlock = i; }
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
index 91a8492..d0660346 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
@@ -83,9 +83,9 @@ public:
}
void VisitChildren(Stmt *S) {
- for (Stmt::child_range I = S->children(); I; ++I)
- if (*I)
- static_cast<CGBuilder*>(this)->Visit(*I);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt)
+ this->Visit(SubStmt);
}
};
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
index 0db3cac..be1262d 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
@@ -25,7 +25,7 @@ using namespace ento;
bool cocoa::isRefType(QualType RetTy, StringRef Prefix,
StringRef Name) {
// Recursively walk the typedef stack, allowing typedefs of reference types.
- while (const TypedefType *TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
+ while (const TypedefType *TD = RetTy->getAs<TypedefType>()) {
StringRef TDName = TD->getDecl()->getIdentifier()->getName();
if (TDName.startswith(Prefix) && TDName.endswith("Ref"))
return true;
diff --git a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
index 2b2da2c..fa985ee 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
@@ -946,10 +946,9 @@ void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
namespace clang {
namespace consumed {
-void splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
- ConsumedStateMap *ThenStates,
- ConsumedStateMap *ElseStates) {
-
+static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
+ ConsumedStateMap *ThenStates,
+ ConsumedStateMap *ElseStates) {
ConsumedState VarState = ThenStates->getState(Test.Var);
if (VarState == CS_Unknown) {
@@ -964,9 +963,9 @@ void splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
}
}
-void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
- ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates) {
-
+static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
+ ConsumedStateMap *ThenStates,
+ ConsumedStateMap *ElseStates) {
const VarTestResult &LTest = PInfo.getLTest(),
&RTest = PInfo.getRTest();
@@ -1443,7 +1442,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
CurrStates,
WarningsHandler);
- if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
+ if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
BlockInfo.discardInfo(*SI);
} else {
BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
diff --git a/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
index 662166c..0948bc0 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
@@ -256,16 +256,17 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
// Methods on ArgType.
//===----------------------------------------------------------------------===//
-bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
+clang::analyze_format_string::ArgType::MatchKind
+ArgType::matchesType(ASTContext &C, QualType argTy) const {
if (Ptr) {
// It has to be a pointer.
const PointerType *PT = argTy->getAs<PointerType>();
if (!PT)
- return false;
+ return NoMatch;
// We cannot write through a const qualified pointer.
if (PT->getPointeeType().isConstQualified())
- return false;
+ return NoMatch;
argTy = PT->getPointeeType();
}
@@ -275,8 +276,8 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
llvm_unreachable("ArgType must be valid");
case UnknownTy:
- return true;
-
+ return Match;
+
case AnyCharTy: {
if (const EnumType *ETy = argTy->getAs<EnumType>())
argTy = ETy->getDecl()->getIntegerType();
@@ -289,18 +290,18 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
case BuiltinType::SChar:
case BuiltinType::UChar:
case BuiltinType::Char_U:
- return true;
+ return Match;
}
- return false;
+ return NoMatch;
}
-
+
case SpecificTy: {
if (const EnumType *ETy = argTy->getAs<EnumType>())
argTy = ETy->getDecl()->getIntegerType();
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
if (T == argTy)
- return true;
+ return Match;
// Check for "compatible types".
if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -309,32 +310,33 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
case BuiltinType::Char_S:
case BuiltinType::SChar:
case BuiltinType::Char_U:
- case BuiltinType::UChar:
- return T == C.UnsignedCharTy || T == C.SignedCharTy;
+ case BuiltinType::UChar:
+ return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
+ : NoMatch;
case BuiltinType::Short:
- return T == C.UnsignedShortTy;
+ return T == C.UnsignedShortTy ? Match : NoMatch;
case BuiltinType::UShort:
- return T == C.ShortTy;
+ return T == C.ShortTy ? Match : NoMatch;
case BuiltinType::Int:
- return T == C.UnsignedIntTy;
+ return T == C.UnsignedIntTy ? Match : NoMatch;
case BuiltinType::UInt:
- return T == C.IntTy;
+ return T == C.IntTy ? Match : NoMatch;
case BuiltinType::Long:
- return T == C.UnsignedLongTy;
+ return T == C.UnsignedLongTy ? Match : NoMatch;
case BuiltinType::ULong:
- return T == C.LongTy;
+ return T == C.LongTy ? Match : NoMatch;
case BuiltinType::LongLong:
- return T == C.UnsignedLongLongTy;
+ return T == C.UnsignedLongLongTy ? Match : NoMatch;
case BuiltinType::ULongLong:
- return T == C.LongLongTy;
+ return T == C.LongLongTy ? Match : NoMatch;
}
- return false;
+ return NoMatch;
}
case CStrTy: {
const PointerType *PT = argTy->getAs<PointerType>();
if (!PT)
- return false;
+ return NoMatch;
QualType pointeeTy = PT->getPointeeType();
if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -343,50 +345,56 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
case BuiltinType::UChar:
case BuiltinType::Char_S:
case BuiltinType::SChar:
- return true;
+ return Match;
default:
break;
}
- return false;
+ return NoMatch;
}
case WCStrTy: {
const PointerType *PT = argTy->getAs<PointerType>();
if (!PT)
- return false;
+ return NoMatch;
QualType pointeeTy =
C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
- return pointeeTy == C.getWideCharType();
+ return pointeeTy == C.getWideCharType() ? Match : NoMatch;
}
-
+
case WIntTy: {
-
+
QualType PromoArg =
argTy->isPromotableIntegerType()
? C.getPromotedIntegerType(argTy) : argTy;
-
+
QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
-
+
// If the promoted argument is the corresponding signed type of the
// wint_t type, then it should match.
if (PromoArg->hasSignedIntegerRepresentation() &&
C.getCorrespondingUnsignedType(PromoArg) == WInt)
- return true;
+ return Match;
- return WInt == PromoArg;
+ return WInt == PromoArg ? Match : NoMatch;
}
case CPointerTy:
- return argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
- argTy->isBlockPointerType() || argTy->isNullPtrType();
+ if (argTy->isVoidPointerType()) {
+ return Match;
+ } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
+ argTy->isBlockPointerType() || argTy->isNullPtrType()) {
+ return NoMatchPedantic;
+ } else {
+ return NoMatch;
+ }
case ObjCPointerTy: {
if (argTy->getAs<ObjCObjectPointerType>() ||
argTy->getAs<BlockPointerType>())
- return true;
-
+ return Match;
+
// Handle implicit toll-free bridging.
if (const PointerType *PT = argTy->getAs<PointerType>()) {
// Things such as CFTypeRef are really just opaque pointers
@@ -395,9 +403,9 @@ bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
// structs can be toll-free bridged, we just accept them all.
QualType pointee = PT->getPointeeType();
if (pointee->getAsStructureType() || pointee->isVoidType())
- return true;
+ return Match;
}
- return false;
+ return NoMatch;
}
}
@@ -791,7 +799,8 @@ bool FormatSpecifier::hasStandardLengthModifier() const {
llvm_unreachable("Invalid LengthModifier Kind!");
}
-bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) const {
+bool FormatSpecifier::hasStandardConversionSpecifier(
+ const LangOptions &LangOpt) const {
switch (CS.getKind()) {
case ConversionSpecifier::cArg:
case ConversionSpecifier::dArg:
diff --git a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
index 86b679c..5e0a9a0 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
@@ -322,11 +322,10 @@ void TransferFunctions::Visit(Stmt *S) {
return;
}
}
-
- for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end();
- it != ei; ++it) {
- if (Stmt *child = *it)
- AddLiveStmt(val.liveStmts, LV.SSetFact, child);
+
+ for (Stmt *Child : S->children()) {
+ if (Child)
+ AddLiveStmt(val.liveStmts, LV.SSetFact, Child);
}
}
@@ -356,11 +355,8 @@ void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
}
void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
- AnalysisDeclContext::referenced_decls_iterator I, E;
- std::tie(I, E) =
- LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
- for ( ; I != E ; ++I) {
- const VarDecl *VD = *I;
+ for (const VarDecl *VD :
+ LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
if (isAlwaysAlive(VD))
continue;
val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
index b8d3ec1..f0976bc 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
@@ -49,6 +49,24 @@ static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
return false;
}
+static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
+ const char *FlagBeg, const char *E, bool Warn) {
+ StringRef Flag(FlagBeg, E - FlagBeg);
+ // Currently there is only one flag.
+ if (Flag == "tt") {
+ FS.setHasObjCTechnicalTerm(FlagBeg);
+ return false;
+ }
+ // Handle either the case of no flag or an invalid flag.
+ if (Warn) {
+ if (Flag == "")
+ H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
+ else
+ H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
+ }
+ return true;
+}
+
static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
const char *&Beg,
const char *E,
@@ -168,6 +186,38 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
+ // Look for the Objective-C modifier flags, if any.
+ // We parse these here, even if they don't apply to
+ // the conversion specifier, and then emit an error
+ // later if the conversion specifier isn't '@'. This
+ // enables better recovery, and we don't know if
+ // these flags are applicable until later.
+ const char *ObjCModifierFlagsStart = nullptr,
+ *ObjCModifierFlagsEnd = nullptr;
+ if (*I == '[') {
+ ObjCModifierFlagsStart = I;
+ ++I;
+ auto flagStart = I;
+ for (;; ++I) {
+ ObjCModifierFlagsEnd = I;
+ if (I == E) {
+ if (Warn)
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ // Did we find the closing ']'?
+ if (*I == ']') {
+ if (ParseObjCFlags(H, FS, flagStart, I, Warn))
+ return true;
+ ++I;
+ break;
+ }
+ // There are no separators defined yet for multiple
+ // Objective-C modifier flags. When those are
+ // defined, this is the place to check.
+ }
+ }
+
if (*I == '\0') {
// Detect spurious null characters, which are likely errors.
H.HandleNullChar(I);
@@ -240,6 +290,18 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
if (Target.getTriple().isOSMSVCRT())
k = ConversionSpecifier::ZArg;
}
+
+ // Check to see if we used the Objective-C modifier flags with
+ // a conversion specifier other than '@'.
+ if (k != ConversionSpecifier::ObjCObjArg &&
+ k != ConversionSpecifier::InvalidSpecifier &&
+ ObjCModifierFlagsStart) {
+ H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
+ ObjCModifierFlagsEnd + 1,
+ conversionPosition);
+ return true;
+ }
+
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp
index 3f96ca8..5b917a7 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -220,8 +220,8 @@ void PseudoConstantAnalysis::RunAnalysis() {
} // switch (head->getStmtClass())
// Add all substatements to the worklist
- for (Stmt::const_child_range I = Head->children(); I; ++I)
- if (*I)
- WorkList.push_back(*I);
+ for (const Stmt *SubStmt : Head->children())
+ if (SubStmt)
+ WorkList.push_back(SubStmt);
} // while (!WorkList.empty())
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
index f45d6e7..e2c6ab5 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
@@ -44,14 +44,13 @@
#include <sstream>
#include <utility>
#include <vector>
-
-
-namespace clang {
-namespace threadSafety {
+using namespace clang;
+using namespace threadSafety;
// Key method definition
ThreadSafetyHandler::~ThreadSafetyHandler() {}
+namespace {
class TILPrinter :
public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
@@ -69,7 +68,6 @@ static void warnInvalidLock(ThreadSafetyHandler &Handler,
Handler.handleInvalidLockExp(Kind, Loc);
}
-
/// \brief A set of CapabilityInfo objects, which are compiled from the
/// requires attributes on a function.
class CapExprSet : public SmallVector<CapabilityExpr, 4> {
@@ -101,17 +99,22 @@ private:
LockKind LKind; ///< exclusive or shared
SourceLocation AcquireLoc; ///< where it was acquired.
bool Asserted; ///< true if the lock was asserted
+ bool Declared; ///< true if the lock was declared
public:
FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
- bool Asrt)
- : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt) {}
+ bool Asrt, bool Declrd = false)
+ : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt),
+ Declared(Declrd) {}
virtual ~FactEntry() {}
- LockKind kind() const { return LKind; }
+ LockKind kind() const { return LKind; }
SourceLocation loc() const { return AcquireLoc; }
bool asserted() const { return Asserted; }
+ bool declared() const { return Declared; }
+
+ void setDeclared(bool D) { Declared = D; }
virtual void
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
@@ -231,14 +234,61 @@ public:
FactEntry *findPartialMatch(FactManager &FM,
const CapabilityExpr &CapE) const {
- auto I = std::find_if(begin(), end(), [&](FactID ID) {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
return FM[ID].partiallyMatches(CapE);
});
return I != end() ? &FM[*I] : nullptr;
}
+
+ bool containsMutexDecl(FactManager &FM, const ValueDecl* Vd) const {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
+ return FM[ID].valueDecl() == Vd;
+ });
+ return I != end();
+ }
};
+class ThreadSafetyAnalyzer;
+} // namespace
+
+namespace clang {
+namespace threadSafety {
+class BeforeSet {
+private:
+ typedef SmallVector<const ValueDecl*, 4> BeforeVect;
+
+ struct BeforeInfo {
+ BeforeInfo() : Vect(nullptr), Visited(false) { }
+ BeforeInfo(BeforeInfo &&O)
+ : Vect(std::move(O.Vect)), Visited(O.Visited)
+ {}
+
+ std::unique_ptr<BeforeVect> Vect;
+ int Visited;
+ };
+
+ typedef llvm::DenseMap<const ValueDecl*, BeforeInfo> BeforeMap;
+ typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
+
+public:
+ BeforeSet() { }
+
+ BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
+ ThreadSafetyAnalyzer& Analyzer);
+
+ void checkBeforeAfter(const ValueDecl* Vd,
+ const FactSet& FSet,
+ ThreadSafetyAnalyzer& Analyzer,
+ SourceLocation Loc, StringRef CapKind);
+
+private:
+ BeforeMap BMap;
+ CycleMap CycMap;
+};
+} // end namespace threadSafety
+} // end namespace clang
+namespace {
typedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
class LocalVariableMap;
@@ -853,6 +903,7 @@ public:
/// \brief Class which implements the core thread safety analysis routines.
class ThreadSafetyAnalyzer {
friend class BuildLockset;
+ friend class threadSafety::BeforeSet;
llvm::BumpPtrAllocator Bpa;
threadSafety::til::MemRegionRef Arena;
@@ -864,9 +915,11 @@ class ThreadSafetyAnalyzer {
FactManager FactMan;
std::vector<CFGBlockInfo> BlockInfo;
+ BeforeSet* GlobalBeforeSet;
+
public:
- ThreadSafetyAnalyzer(ThreadSafetyHandler &H)
- : Arena(&Bpa), SxBuilder(Arena), Handler(H) {}
+ ThreadSafetyAnalyzer(ThreadSafetyHandler &H, BeforeSet* Bset)
+ : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
bool inCurrentScope(const CapabilityExpr &CapE);
@@ -906,6 +959,134 @@ public:
void runAnalysis(AnalysisDeclContext &AC);
};
+} // namespace
+
+/// Process acquired_before and acquired_after attributes on Vd.
+BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
+ ThreadSafetyAnalyzer& Analyzer) {
+ // Create a new entry for Vd.
+ auto& Entry = BMap.FindAndConstruct(Vd);
+ BeforeInfo* Info = &Entry.second;
+ BeforeVect* Bv = nullptr;
+
+ for (Attr* At : Vd->attrs()) {
+ switch (At->getKind()) {
+ case attr::AcquiredBefore: {
+ auto *A = cast<AcquiredBeforeAttr>(At);
+
+ // Create a new BeforeVect for Vd if necessary.
+ if (!Bv) {
+ Bv = new BeforeVect;
+ Info->Vect.reset(Bv);
+ }
+ // Read exprs from the attribute, and add them to BeforeVect.
+ for (const auto *Arg : A->args()) {
+ CapabilityExpr Cp =
+ Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
+ if (const ValueDecl *Cpvd = Cp.valueDecl()) {
+ Bv->push_back(Cpvd);
+ auto It = BMap.find(Cpvd);
+ if (It == BMap.end())
+ insertAttrExprs(Cpvd, Analyzer);
+ }
+ }
+ break;
+ }
+ case attr::AcquiredAfter: {
+ auto *A = cast<AcquiredAfterAttr>(At);
+
+ // Read exprs from the attribute, and add them to BeforeVect.
+ for (const auto *Arg : A->args()) {
+ CapabilityExpr Cp =
+ Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
+ if (const ValueDecl *ArgVd = Cp.valueDecl()) {
+ // Get entry for mutex listed in attribute
+ BeforeInfo* ArgInfo;
+ auto It = BMap.find(ArgVd);
+ if (It == BMap.end())
+ ArgInfo = insertAttrExprs(ArgVd, Analyzer);
+ else
+ ArgInfo = &It->second;
+
+ // Create a new BeforeVect if necessary.
+ BeforeVect* ArgBv = ArgInfo->Vect.get();
+ if (!ArgBv) {
+ ArgBv = new BeforeVect;
+ ArgInfo->Vect.reset(ArgBv);
+ }
+ ArgBv->push_back(Vd);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return Info;
+}
+
+
+/// Return true if any mutexes in FSet are in the acquired_before set of Vd.
+void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
+ const FactSet& FSet,
+ ThreadSafetyAnalyzer& Analyzer,
+ SourceLocation Loc, StringRef CapKind) {
+ SmallVector<BeforeInfo*, 8> InfoVect;
+
+ // Do a depth-first traversal of Vd.
+ // Return true if there are cycles.
+ std::function<bool (const ValueDecl*)> traverse = [&](const ValueDecl* Vd) {
+ if (!Vd)
+ return false;
+
+ BeforeSet::BeforeInfo* Info;
+ auto It = BMap.find(Vd);
+ if (It == BMap.end())
+ Info = insertAttrExprs(Vd, Analyzer);
+ else
+ Info = &It->second;
+
+ if (Info->Visited == 1)
+ return true;
+
+ if (Info->Visited == 2)
+ return false;
+
+ BeforeVect* Bv = Info->Vect.get();
+ if (!Bv)
+ return false;
+
+ InfoVect.push_back(Info);
+ Info->Visited = 1;
+ for (auto *Vdb : *Bv) {
+ // Exclude mutexes in our immediate before set.
+ if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
+ StringRef L1 = StartVd->getName();
+ StringRef L2 = Vdb->getName();
+ Analyzer.Handler.handleLockAcquiredBefore(CapKind, L1, L2, Loc);
+ }
+ // Transitively search other before sets, and warn on cycles.
+ if (traverse(Vdb)) {
+ if (CycMap.find(Vd) == CycMap.end()) {
+ CycMap.insert(std::make_pair(Vd, true));
+ StringRef L1 = Vd->getName();
+ Analyzer.Handler.handleBeforeAfterCycle(L1, Vd->getLocation());
+ }
+ }
+ }
+ Info->Visited = 2;
+ return false;
+ };
+
+ traverse(StartVd);
+
+ for (auto* Info : InfoVect)
+ Info->Visited = 0;
+}
+
+
/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
static const ValueDecl *getValueDecl(const Expr *Exp) {
@@ -921,6 +1102,7 @@ static const ValueDecl *getValueDecl(const Expr *Exp) {
return nullptr;
}
+namespace {
template <typename Ty>
class has_arg_iterator_range {
typedef char yes[1];
@@ -935,6 +1117,7 @@ class has_arg_iterator_range {
public:
static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
};
+} // namespace
static StringRef ClassifyDiagnostic(const CapabilityAttr *A) {
return A->getName();
@@ -1020,7 +1203,13 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
}
}
- // FIXME: deal with acquired before/after annotations.
+ // Check before/after constraints
+ if (Handler.issueBetaWarnings() &&
+ !Entry->asserted() && !Entry->declared()) {
+ GlobalBeforeSet->checkBeforeAfter(Entry->valueDecl(), FSet, *this,
+ Entry->loc(), DiagKind);
+ }
+
// FIXME: Don't always warn when we have support for reentrant locks.
if (FSet.findLock(FactMan, *Entry)) {
if (!Entry->asserted())
@@ -1119,8 +1308,7 @@ void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
}
}
-
-bool getStaticBooleanValue(Expr* E, bool& TCond) {
+static bool getStaticBooleanValue(Expr *E, bool &TCond) {
if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
TCond = false;
return true;
@@ -1230,7 +1418,7 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
CapExprSet SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- for (auto *Attr : FunDecl->getAttrs()) {
+ for (auto *Attr : FunDecl->attrs()) {
switch (Attr->getKind()) {
case attr::ExclusiveTrylockFunction: {
ExclusiveTrylockFunctionAttr *A =
@@ -1265,6 +1453,7 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
CapDiagKind);
}
+namespace {
/// \brief We use this class to visit different types of expressions in
/// CFGBlocks, and build up the lockset.
/// An expression may cause us to add or remove locks from the lockset, or else
@@ -1308,7 +1497,7 @@ public:
void VisitCXXConstructExpr(CXXConstructExpr *Exp);
void VisitDeclStmt(DeclStmt *S);
};
-
+} // namespace
/// \brief Warn if the LSet does not contain a lock sufficient to protect access
/// of at least the passed in AccessKind.
@@ -1500,13 +1689,23 @@ void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK,
///
void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
SourceLocation Loc = Exp->getExprLoc();
- const AttrVec &ArgAttrs = D->getAttrs();
CapExprSet ExclusiveLocksToAdd, SharedLocksToAdd;
CapExprSet ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
+ CapExprSet ScopedExclusiveReqs, ScopedSharedReqs;
StringRef CapDiagKind = "mutex";
- for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
- Attr *At = const_cast<Attr*>(ArgAttrs[i]);
+ // Figure out if we're calling the constructor of scoped lockable class
+ bool isScopedVar = false;
+ if (VD) {
+ if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
+ const CXXRecordDecl* PD = CD->getParent();
+ if (PD && PD->hasAttr<ScopedLockableAttr>())
+ isScopedVar = true;
+ }
+ }
+
+ for(Attr *Atconst : D->attrs()) {
+ Attr* At = const_cast<Attr*>(Atconst);
switch (At->getKind()) {
// When we encounter a lock function, we need to add the lock to our
// lockset.
@@ -1564,10 +1763,17 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
case attr::RequiresCapability: {
RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
- for (auto *Arg : A->args())
+ for (auto *Arg : A->args()) {
warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
POK_FunctionCall, ClassifyDiagnostic(A),
Exp->getExprLoc());
+ // use for adopting a lock
+ if (isScopedVar) {
+ Analyzer->getMutexIDs(A->isShared() ? ScopedSharedReqs
+ : ScopedExclusiveReqs,
+ A, Exp, D, VD);
+ }
+ }
break;
}
@@ -1584,16 +1790,6 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
}
}
- // Figure out if we're calling the constructor of scoped lockable class
- bool isScopedVar = false;
- if (VD) {
- if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
- const CXXRecordDecl* PD = CD->getParent();
- if (PD && PD->hasAttr<ScopedLockableAttr>())
- isScopedVar = true;
- }
- }
-
// Add locks.
for (const auto &M : ExclusiveLocksToAdd)
Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>(
@@ -1611,9 +1807,10 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
// FIXME: does this store a pointer to DRE?
CapabilityExpr Scp = Analyzer->SxBuilder.translateAttrExpr(&DRE, nullptr);
- CapExprSet UnderlyingMutexes(ExclusiveLocksToAdd);
- std::copy(SharedLocksToAdd.begin(), SharedLocksToAdd.end(),
- std::back_inserter(UnderlyingMutexes));
+ std::copy(ScopedExclusiveReqs.begin(), ScopedExclusiveReqs.end(),
+ std::back_inserter(ExclusiveLocksToAdd));
+ std::copy(ScopedSharedReqs.begin(), ScopedSharedReqs.end(),
+ std::back_inserter(SharedLocksToAdd));
Analyzer->addLock(FSet,
llvm::make_unique<ScopedLockableFactEntry>(
Scp, MLoc, ExclusiveLocksToAdd, SharedLocksToAdd),
@@ -1863,7 +2060,7 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
// Return true if block B never continues to its successors.
-inline bool neverReturns(const CFGBlock* B) {
+static bool neverReturns(const CFGBlock *B) {
if (B->hasNoReturnElement())
return true;
if (B->empty())
@@ -1940,14 +2137,13 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
if (!SortedGraph->empty() && D->hasAttrs()) {
const CFGBlock *FirstBlock = *SortedGraph->begin();
FactSet &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
- const AttrVec &ArgAttrs = D->getAttrs();
CapExprSet ExclusiveLocksToAdd;
CapExprSet SharedLocksToAdd;
StringRef CapDiagKind = "mutex";
SourceLocation Loc = D->getLocation();
- for (const auto *Attr : ArgAttrs) {
+ for (const auto *Attr : D->attrs()) {
Loc = Attr->getLocation();
if (const auto *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
@@ -1979,14 +2175,16 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
}
// FIXME -- Loc can be wrong here.
- for (const auto &Mu : ExclusiveLocksToAdd)
- addLock(InitialLockset,
- llvm::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc),
- CapDiagKind, true);
- for (const auto &Mu : SharedLocksToAdd)
- addLock(InitialLockset,
- llvm::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc),
- CapDiagKind, true);
+ for (const auto &Mu : ExclusiveLocksToAdd) {
+ auto Entry = llvm::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc);
+ Entry->setDeclared(true);
+ addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
+ }
+ for (const auto &Mu : SharedLocksToAdd) {
+ auto Entry = llvm::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc);
+ Entry->setDeclared(true);
+ addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
+ }
}
for (const auto *CurrBlock : *SortedGraph) {
@@ -2179,15 +2377,20 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
-void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
- ThreadSafetyHandler &Handler) {
- ThreadSafetyAnalyzer Analyzer(Handler);
+void threadSafety::runThreadSafetyAnalysis(AnalysisDeclContext &AC,
+ ThreadSafetyHandler &Handler,
+ BeforeSet **BSet) {
+ if (!*BSet)
+ *BSet = new BeforeSet;
+ ThreadSafetyAnalyzer Analyzer(Handler, *BSet);
Analyzer.runAnalysis(AC);
}
+void threadSafety::threadSafetyCleanup(BeforeSet *Cache) { delete Cache; }
+
/// \brief Helper function that returns a LockKind required for the given level
/// of access.
-LockKind getLockKindFromAccessKind(AccessKind AK) {
+LockKind threadSafety::getLockKindFromAccessKind(AccessKind AK) {
switch (AK) {
case AK_Read :
return LK_Shared;
@@ -2196,5 +2399,3 @@ LockKind getLockKindFromAccessKind(AccessKind AK) {
}
llvm_unreachable("Unknown AccessKind");
}
-
-}} // end namespace clang::threadSafety
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 563e059..d4b1ce2 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -31,13 +31,11 @@
#include <algorithm>
#include <climits>
#include <vector>
-
-
-namespace clang {
-namespace threadSafety {
+using namespace clang;
+using namespace threadSafety;
// From ThreadSafetyUtil.h
-std::string getSourceLiteralString(const clang::Expr *CE) {
+std::string threadSafety::getSourceLiteralString(const clang::Expr *CE) {
switch (CE->getStmtClass()) {
case Stmt::IntegerLiteralClass:
return cast<IntegerLiteral>(CE)->getValue().toString(10, true);
@@ -59,18 +57,13 @@ std::string getSourceLiteralString(const clang::Expr *CE) {
}
}
-namespace til {
-
// Return true if E is a variable that points to an incomplete Phi node.
-static bool isIncompletePhi(const SExpr *E) {
- if (const auto *Ph = dyn_cast<Phi>(E))
- return Ph->status() == Phi::PH_Incomplete;
+static bool isIncompletePhi(const til::SExpr *E) {
+ if (const auto *Ph = dyn_cast<til::Phi>(E))
+ return Ph->status() == til::Phi::PH_Incomplete;
return false;
}
-} // end namespace til
-
-
typedef SExprBuilder::CallingContext CallingContext;
@@ -87,9 +80,7 @@ til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
return Scfg;
}
-
-
-inline bool isCalleeArrow(const Expr *E) {
+static bool isCalleeArrow(const Expr *E) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
return ME ? ME->isArrow() : false;
}
@@ -313,8 +304,7 @@ til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
return SelfVar;
}
-
-const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
+static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
if (auto *V = dyn_cast<til::Variable>(E))
return V->clangDecl();
if (auto *Ph = dyn_cast<til::Phi>(E))
@@ -326,7 +316,7 @@ const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
return 0;
}
-bool hasCppPointerType(const til::SExpr *E) {
+static bool hasCppPointerType(const til::SExpr *E) {
auto *VD = getValueDeclFromSExpr(E);
if (VD && VD->getType()->isPointerType())
return true;
@@ -336,9 +326,8 @@ bool hasCppPointerType(const til::SExpr *E) {
return false;
}
-
// Grab the very first declaration of virtual method D
-const CXXMethodDecl* getFirstVirtualDecl(const CXXMethodDecl *D) {
+static const CXXMethodDecl *getFirstVirtualDecl(const CXXMethodDecl *D) {
while (true) {
D = D->getCanonicalDecl();
CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
@@ -663,7 +652,7 @@ til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
// if E is a til::Variable, update its clangDecl.
-inline void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
+static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
if (!E)
return;
if (til::Variable *V = dyn_cast<til::Variable>(E)) {
@@ -986,8 +975,3 @@ void printSCFG(CFGWalker &Walker) {
TILPrinter::print(Scfg, llvm::errs());
}
*/
-
-
-} // end namespace threadSafety
-
-} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
index ebe374e..2923f7e6 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
@@ -9,13 +9,11 @@
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+using namespace clang;
+using namespace threadSafety;
+using namespace til;
-namespace clang {
-namespace threadSafety {
-namespace til {
-
-
-StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op) {
+StringRef til::getUnaryOpcodeString(TIL_UnaryOpcode Op) {
switch (Op) {
case UOP_Minus: return "-";
case UOP_BitNot: return "~";
@@ -24,8 +22,7 @@ StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op) {
return "";
}
-
-StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op) {
+StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
switch (Op) {
case BOP_Mul: return "*";
case BOP_Div: return "/";
@@ -82,7 +79,7 @@ void BasicBlock::reservePredecessors(unsigned NumPreds) {
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
-const SExpr *getCanonicalVal(const SExpr *E) {
+const SExpr *til::getCanonicalVal(const SExpr *E) {
while (true) {
if (auto *V = dyn_cast<Variable>(E)) {
if (V->kind() == Variable::VK_Let) {
@@ -105,7 +102,7 @@ const SExpr *getCanonicalVal(const SExpr *E) {
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
// The non-const version will simplify incomplete Phi nodes.
-SExpr *simplifyToCanonicalVal(SExpr *E) {
+SExpr *til::simplifyToCanonicalVal(SExpr *E) {
while (true) {
if (auto *V = dyn_cast<Variable>(E)) {
if (V->kind() != Variable::VK_Let)
@@ -135,7 +132,7 @@ SExpr *simplifyToCanonicalVal(SExpr *E) {
// Trace the arguments of an incomplete Phi node to see if they have the same
// canonical definition. If so, mark the Phi node as redundant.
// getCanonicalVal() will recursively call simplifyIncompletePhi().
-void simplifyIncompleteArg(til::Phi *Ph) {
+void til::simplifyIncompleteArg(til::Phi *Ph) {
assert(Ph && Ph->status() == Phi::PH_Incomplete);
// eliminate infinite recursion -- assume that this node is not redundant.
@@ -337,7 +334,3 @@ void SCFG::computeNormalForm() {
computeNodeID(Block, &BasicBlock::PostDominatorNode);
}
}
-
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
index 61a2592..f2f7919 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
@@ -35,9 +36,9 @@ using namespace clang;
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
!vd->isExceptionVariable() && !vd->isInitCapture() &&
- vd->getDeclContext() == dc) {
+ !vd->isImplicit() && vd->getDeclContext() == dc) {
QualType ty = vd->getType();
- return ty->isScalarType() || ty->isVectorType();
+ return ty->isScalarType() || ty->isVectorType() || ty->isRecordType();
}
return false;
}
@@ -347,6 +348,7 @@ public:
}
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
+ if (VD->getType()->isRecordType()) return nullptr;
if (Expr *Init = VD->getInit()) {
const DeclRefExpr *DRE
= dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
@@ -376,10 +378,26 @@ void ClassifyRefs::classify(const Expr *E, Class C) {
return;
}
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
+ if (!VD->isStaticDataMember())
+ classify(ME->getBase(), C);
+ }
+ return;
+ }
+
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->getOpcode() == BO_Comma)
+ switch (BO->getOpcode()) {
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ classify(BO->getLHS(), C);
+ return;
+ case BO_Comma:
classify(BO->getRHS(), C);
- return;
+ return;
+ default:
+ return;
+ }
}
FindVarResult Var = findVar(E, DC);
@@ -404,7 +422,7 @@ void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) {
// use.
if (BO->isCompoundAssignmentOp())
classify(BO->getLHS(), Use);
- else if (BO->getOpcode() == BO_Assign)
+ else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma)
classify(BO->getLHS(), Ignore);
}
@@ -415,25 +433,40 @@ void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) {
classify(UO->getSubExpr(), Use);
}
+static bool isPointerToConst(const QualType &QT) {
+ return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified();
+}
+
void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
// Classify arguments to std::move as used.
if (CE->getNumArgs() == 1) {
if (FunctionDecl *FD = CE->getDirectCallee()) {
if (FD->isInStdNamespace() && FD->getIdentifier() &&
FD->getIdentifier()->isStr("move")) {
- classify(CE->getArg(0), Use);
+ // RecordTypes are handled in SemaDeclCXX.cpp.
+ if (!CE->getArg(0)->getType()->isRecordType())
+ classify(CE->getArg(0), Use);
return;
}
}
}
- // If a value is passed by const reference to a function, we should not assume
- // that it is initialized by the call, and we conservatively do not assume
- // that it is used.
+ // If a value is passed by const pointer or by const reference to a function,
+ // we should not assume that it is initialized by the call, and we
+ // conservatively do not assume that it is used.
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
- I != E; ++I)
- if ((*I)->getType().isConstQualified() && (*I)->isGLValue())
- classify(*I, Ignore);
+ I != E; ++I) {
+ if ((*I)->isGLValue()) {
+ if ((*I)->getType().isConstQualified())
+ classify((*I), Ignore);
+ } else if (isPointerToConst((*I)->getType())) {
+ const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
+ const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex);
+ if (UO && UO->getOpcode() == UO_AddrOf)
+ Ex = UO->getSubExpr();
+ classify(Ex, Ignore);
+ }
+ }
}
void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
@@ -804,7 +837,7 @@ struct PruneBlocksHandler : public UninitVariablesHandler {
: hadUse(numBlocks, false), hadAnyUse(false),
currentBlock(0) {}
- virtual ~PruneBlocksHandler() {}
+ ~PruneBlocksHandler() override {}
/// Records if a CFGBlock had a potential use of an uninitialized variable.
llvm::BitVector hadUse;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
index 83228ad..f89caf7 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -24,6 +24,27 @@
using namespace clang;
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ DiagNullabilityKind nullability) {
+ StringRef string;
+ switch (nullability.first) {
+ case NullabilityKind::NonNull:
+ string = nullability.second ? "'nonnull'" : "'_Nonnull'";
+ break;
+
+ case NullabilityKind::Nullable:
+ string = nullability.second ? "'nullable'" : "'_Nullable'";
+ break;
+
+ case NullabilityKind::Unspecified:
+ string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
+ break;
+ }
+
+ DB.AddString(string);
+ return DB;
+}
+
static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
StringRef Modifier, StringRef Argument,
ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
@@ -112,7 +133,7 @@ void DiagnosticsEngine::Reset() {
// Create a DiagState and DiagStatePoint representing diagnostic changes
// through command-line.
- DiagStates.push_back(DiagState());
+ DiagStates.emplace_back();
DiagStatePoints.push_back(DiagStatePoint(&DiagStates.back(), FullSourceLoc()));
}
@@ -321,18 +342,10 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
NumDiagArgs = 0;
DiagRanges.clear();
- DiagRanges.reserve(storedDiag.range_size());
- for (StoredDiagnostic::range_iterator
- RI = storedDiag.range_begin(),
- RE = storedDiag.range_end(); RI != RE; ++RI)
- DiagRanges.push_back(*RI);
+ DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end());
DiagFixItHints.clear();
- DiagFixItHints.reserve(storedDiag.fixit_size());
- for (StoredDiagnostic::fixit_iterator
- FI = storedDiag.fixit_begin(),
- FE = storedDiag.fixit_end(); FI != FE; ++FI)
- DiagFixItHints.push_back(*FI);
+ DiagFixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end());
assert(Client && "DiagnosticConsumer not set!");
Level DiagLevel = storedDiag.getLevel();
@@ -633,7 +646,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
// When the diagnostic string is only "%0", the entire string is being given
// by an outside source. Remove unprintable characters from this string
// and skip all the other string processing.
- if (DiagEnd - DiagStr == 2 && DiagStr[0] == '%' && DiagStr[1] == '0' &&
+ if (DiagEnd - DiagStr == 2 &&
+ StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") &&
getArgKind(0) == DiagnosticsEngine::ak_std_string) {
const std::string &S = getArgStdStr(0);
for (char c : S) {
@@ -948,14 +962,8 @@ StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
SmallString<64> Message;
Info.FormatDiagnostic(Message);
this->Message.assign(Message.begin(), Message.end());
-
- Ranges.reserve(Info.getNumRanges());
- for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
- Ranges.push_back(Info.getRange(I));
-
- FixIts.reserve(Info.getNumFixItHints());
- for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
- FixIts.push_back(Info.getFixItHint(I));
+ this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
+ this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
}
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 1c68375..643503b 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -528,7 +528,7 @@ static bool getDiagnosticsInGroup(diag::Flavor Flavor,
// An empty group is considered to be a warning group: we have empty groups
// for GCC compatibility, and GCC does not have remarks.
if (!Group->Members && !Group->SubGroups)
- return Flavor == diag::Flavor::Remark ? true : false;
+ return Flavor == diag::Flavor::Remark;
bool NotFound = true;
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
new file mode 100644
index 0000000..f54a0ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticOptions.cpp
@@ -0,0 +1,24 @@
+//===--- DiagnosticOptions.cpp - C Language Family Diagnostic Handling ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DiagnosticOptions related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M) {
+ using UT = std::underlying_type<DiagnosticLevelMask>::type;
+ return Out << static_cast<UT>(M);
+}
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
index 214e0f3..1a636ae 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/contrib/llvm/tools/clang/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"
@@ -430,7 +431,7 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
SmallString<128> FilePath(Entry->getName());
FixupRelativePath(FilePath);
- return FS->getBufferForFile(FilePath.str(), FileSize,
+ return FS->getBufferForFile(FilePath, FileSize,
/*RequiresNullTerminator=*/true, isVolatile);
}
@@ -585,3 +586,5 @@ void FileManager::PrintStats() const {
//llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
+
+PCHContainerOperations::~PCHContainerOperations() {}
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
index 83e42bd..187ea37 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
@@ -15,19 +15,8 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/Support/Path.h"
-// FIXME: This is terrible, we need this for ::close.
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#include <sys/uio.h>
-#else
-#include <io.h>
-#endif
using namespace clang;
-#if defined(_MSC_VER)
-#define S_ISDIR(s) ((_S_IFDIR & s) !=0)
-#endif
-
void FileSystemStatCache::anchor() { }
static void copyStatusToFileData(const vfs::Status &Status,
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
index 613b43f..dcb7603 100644
--- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallString.h"
@@ -35,7 +36,7 @@ IdentifierInfo::IdentifierInfo() {
HasMacro = false;
HadMacro = false;
IsExtension = false;
- IsCXX11CompatKeyword = false;
+ IsFutureCompatKeyword = false;
IsPoisoned = false;
IsCPPOperatorKeyword = false;
NeedsHandleIdentifier = false;
@@ -70,8 +71,6 @@ IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
return new EmptyLookupIterator();
}
-ExternalIdentifierLookup::~ExternalIdentifierLookup() {}
-
IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
IdentifierInfoLookup* externalLookup)
: HashTable(8192), // Start with space for 8K identifiers.
@@ -105,10 +104,14 @@ namespace {
KEYOPENCL = 0x200,
KEYC11 = 0x400,
KEYARC = 0x800,
- KEYNOMS = 0x01000,
- WCHARSUPPORT = 0x02000,
- HALFSUPPORT = 0x04000,
- KEYALL = (0xffff & ~KEYNOMS) // Because KEYNOMS is used to exclude.
+ KEYNOMS18 = 0x01000,
+ KEYNOOPENCL = 0x02000,
+ WCHARSUPPORT = 0x04000,
+ HALFSUPPORT = 0x08000,
+ KEYCONCEPTS = 0x10000,
+ KEYOBJC2 = 0x20000,
+ KEYALL = (0x3ffff & ~KEYNOMS18 &
+ ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
/// \brief How a keyword is treated in the selected standard.
@@ -141,6 +144,8 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
// We treat bridge casts as objective-C keywords so we can warn on them
// in non-arc mode.
if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
+ if (LangOpts.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;
}
@@ -154,15 +159,21 @@ static void AddKeyword(StringRef Keyword,
KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
// Don't add this keyword under MSVCCompat.
- if (LangOpts.MSVCCompat && (Flags & KEYNOMS))
- return;
+ if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
+ !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
+ return;
+
+ // Don't add this keyword under OpenCL.
+ if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
+ return;
+
// Don't add this keyword if disabled in this language.
if (AddResult == KS_Disabled) return;
IdentifierInfo &Info =
Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
Info.setIsExtensionToken(AddResult == KS_Extension);
- Info.setIsCXX11CompatKeyword(AddResult == KS_Future);
+ Info.setIsFutureCompatKeyword(AddResult == KS_Future);
}
/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
@@ -207,6 +218,12 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
if (LangOpts.ParseUnknownAnytype)
AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
LangOpts, *this);
+
+ // FIXME: __declspec isn't really a CUDA extension, however it is required for
+ // supporting cuda_builtin_vars.h, which uses __declspec(property). Once that
+ // has been rewritten in terms of something more generic, remove this code.
+ if (LangOpts.CUDA)
+ AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
}
/// \brief Checks if the specified token kind represents a keyword in the
@@ -629,3 +646,18 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
llvm_unreachable("Invalid OverloadedOperatorKind!");
}
+
+StringRef clang::getNullabilitySpelling(NullabilityKind kind,
+ bool isContextSensitive) {
+ switch (kind) {
+ case NullabilityKind::NonNull:
+ return isContextSensitive ? "nonnull" : "_Nonnull";
+
+ case NullabilityKind::Nullable:
+ return isContextSensitive ? "nullable" : "_Nullable";
+
+ case NullabilityKind::Unspecified:
+ return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
+ }
+ llvm_unreachable("Unknown nullability kind.");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
index dcbd228..2c87845 100644
--- a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
@@ -30,7 +30,7 @@ void LangOptions::resetNonModularOptions() {
// FIXME: This should not be reset; modules can be different with different
// sanitizer options (this affects __has_feature(address_sanitizer) etc).
Sanitize.clear();
- SanitizerBlacklistFile.clear();
+ SanitizerBlacklistFiles.clear();
CurrentModule.clear();
ImplementationOfModule.clear();
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
index 03f9bd3..3846fec 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -25,14 +25,14 @@
using namespace clang;
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
- bool IsFramework, bool IsExplicit)
+ bool IsFramework, bool IsExplicit, unsigned VisibilityID)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
- Umbrella(), ASTFile(nullptr), IsMissingRequirement(false),
- IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
- IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
- IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
- InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) {
+ Umbrella(), Signature(0), ASTFile(nullptr), VisibilityID(VisibilityID),
+ IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
+ IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
+ IsExternC(false), IsInferred(false), InferSubmodules(false),
+ InferExplicitSubmodules(false), InferExportWildcard(false),
+ ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -58,16 +58,21 @@ Module::~Module() {
/// language options has the given feature.
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
const TargetInfo &Target) {
- return llvm::StringSwitch<bool>(Feature)
- .Case("altivec", LangOpts.AltiVec)
- .Case("blocks", LangOpts.Blocks)
- .Case("cplusplus", LangOpts.CPlusPlus)
- .Case("cplusplus11", LangOpts.CPlusPlus11)
- .Case("objc", LangOpts.ObjC1)
- .Case("objc_arc", LangOpts.ObjCAutoRefCount)
- .Case("opencl", LangOpts.OpenCL)
- .Case("tls", Target.isTLSSupported())
- .Default(Target.hasFeature(Feature));
+ bool HasFeature = llvm::StringSwitch<bool>(Feature)
+ .Case("altivec", LangOpts.AltiVec)
+ .Case("blocks", LangOpts.Blocks)
+ .Case("cplusplus", LangOpts.CPlusPlus)
+ .Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("objc", LangOpts.ObjC1)
+ .Case("objc_arc", LangOpts.ObjCAutoRefCount)
+ .Case("opencl", LangOpts.OpenCL)
+ .Case("tls", Target.isTLSSupported())
+ .Default(Target.hasFeature(Feature));
+ if (!HasFeature)
+ HasFeature = std::find(LangOpts.ModuleFeatures.begin(),
+ LangOpts.ModuleFeatures.end(),
+ Feature) != LangOpts.ModuleFeatures.end();
+ return HasFeature;
}
bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
@@ -77,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) {
@@ -88,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");
@@ -133,11 +138,11 @@ std::string Module::getFullModuleName() const {
return Result;
}
-const DirectoryEntry *Module::getUmbrellaDir() const {
- if (const FileEntry *Header = getUmbrellaHeader())
- return Header->getDir();
+Module::DirectoryName Module::getUmbrellaDir() const {
+ if (Header U = getUmbrellaHeader())
+ return {"", U.Entry->getDir()};
- return Umbrella.dyn_cast<const DirectoryEntry *>();
+ return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
}
ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
@@ -153,6 +158,19 @@ ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
}
+bool Module::directlyUses(const Module *Requested) const {
+ auto *Top = getTopLevelModule();
+
+ // A top-level module implicitly uses itself.
+ if (Requested->isSubModuleOf(Top))
+ return true;
+
+ for (auto *Use : Top->DirectUses)
+ if (Requested->isSubModuleOf(Use))
+ return true;
+ return false;
+}
+
void Module::addRequirement(StringRef Feature, bool RequiredState,
const LangOptions &LangOpts,
const TargetInfo &Target) {
@@ -166,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;
@@ -175,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;
@@ -183,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);
}
}
@@ -316,15 +338,15 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS << "\n";
}
- if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
+ if (Header H = getUmbrellaHeader()) {
OS.indent(Indent + 2);
OS << "umbrella header \"";
- OS.write_escaped(UmbrellaHeader->getName());
+ OS.write_escaped(H.NameAsWritten);
OS << "\"\n";
- } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) {
+ } else if (DirectoryName D = getUmbrellaDir()) {
OS.indent(Indent + 2);
OS << "umbrella \"";
- OS.write_escaped(UmbrellaDir->getName());
+ OS.write_escaped(D.NameAsWritten);
OS << "\"\n";
}
@@ -457,4 +479,47 @@ void Module::dump() const {
print(llvm::errs());
}
+void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
+ VisibleCallback Vis, ConflictCallback Cb) {
+ if (isVisible(M))
+ return;
+ ++Generation;
+
+ struct Visiting {
+ Module *M;
+ Visiting *ExportedBy;
+ };
+
+ std::function<void(Visiting)> VisitModule = [&](Visiting V) {
+ // Modules that aren't available cannot be made visible.
+ if (!V.M->isAvailable())
+ return;
+
+ // Nothing to do for a module that's already visible.
+ unsigned ID = V.M->getVisibilityID();
+ if (ImportLocs.size() <= ID)
+ ImportLocs.resize(ID + 1);
+ else if (ImportLocs[ID].isValid())
+ return;
+
+ ImportLocs[ID] = Loc;
+ Vis(M);
+
+ // Make any exported modules visible.
+ SmallVector<Module *, 16> Exports;
+ V.M->getExportedModules(Exports);
+ for (Module *E : Exports)
+ VisitModule({E, &V});
+
+ for (auto &C : V.M->Conflicts) {
+ if (isVisible(C.Other)) {
+ llvm::SmallVector<Module*, 8> Path;
+ for (Visiting *I = &V; I; I = I->ExportedBy)
+ Path.push_back(I->M);
+ Cb(Path, C.Other, C.Message);
+ }
+ }
+ };
+ VisitModule({M, nullptr});
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
index 6e98d48..b7407f6 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -91,6 +91,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_SCHEDULE_unknown);
+ case OMPC_depend:
+ return llvm::StringSwitch<OpenMPDependClauseKind>(Str)
+#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEPEND_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -154,6 +159,15 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
+ case OMPC_depend:
+ switch (Type) {
+ case OMPC_DEPEND_unknown:
+ return "unknown";
+#define OPENMP_DEPEND_KIND(Name) \
+ case OMPC_DEPEND_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
llvm_unreachable("Invalid OpenMP 'schedule' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
@@ -332,6 +346,9 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
case OMPD_ordered:
break;
}
@@ -374,7 +391,6 @@ bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
}
bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
- return Kind == OMPC_threadprivate ||
- Kind == OMPC_copyin; // TODO add next clauses like 'copyprivate'.
+ return Kind == OMPC_threadprivate || Kind == OMPC_copyin;
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
index ea5b8d0..095fcd6 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
@@ -15,9 +15,9 @@
using namespace clang;
-SanitizerBlacklist::SanitizerBlacklist(StringRef BlacklistPath,
- SourceManager &SM)
- : SCL(llvm::SpecialCaseList::createOrDie(BlacklistPath)), SM(SM) {}
+SanitizerBlacklist::SanitizerBlacklist(
+ const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
+ : SCL(llvm::SpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
bool SanitizerBlacklist::isBlacklistedGlobal(StringRef GlobalName,
StringRef Category) const {
diff --git a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
index e9aaa36..91b6b2d 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Sanitizers.cpp
@@ -11,25 +11,27 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
-SanitizerSet::SanitizerSet() : Kinds(0) {}
-
-bool SanitizerSet::has(SanitizerKind K) const {
- unsigned Bit = static_cast<unsigned>(K);
- return Kinds & (1 << Bit);
-}
-
-void SanitizerSet::set(SanitizerKind K, bool Value) {
- unsigned Bit = static_cast<unsigned>(K);
- Kinds = Value ? (Kinds | (1 << Bit)) : (Kinds & ~(1 << Bit));
-}
-
-void SanitizerSet::clear() {
- Kinds = 0;
+SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
+ SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
+#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : 0)
+#include "clang/Basic/Sanitizers.def"
+ .Default(0);
+ return ParsedKind;
}
-bool SanitizerSet::empty() const {
- return Kinds == 0;
+SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) {
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ if (Kinds & SanitizerKind::ID##Group) \
+ Kinds |= SanitizerKind::ID;
+#include "clang/Basic/Sanitizers.def"
+ return Kinds;
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
index 6b885a7..d254e86 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
@@ -134,7 +134,7 @@ const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
assert(isValid());
- return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();;
+ return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();
}
std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index 118e3f3..c0b0453 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -110,8 +110,8 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
// possible.
if (!BufferOrError) {
StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
- Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(),
- "<invalid>").release());
+ Buffer.setPointer(MemoryBuffer::getNewUninitMemBuffer(
+ ContentsEntry->getSize(), "<invalid>").release());
char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
index 871bbd5..dbd2f9a 100644
--- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -36,6 +36,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
SuitableAlign = 64;
+ DefaultAlignForAttributeAligned = 128;
MinGlobalAlign = 0;
HalfWidth = 16;
HalfAlign = 16;
@@ -49,6 +50,8 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
MaxVectorAlign = 0;
+ MaxTLSAlign = 0;
+ SimdDefaultAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntMaxType = SignedLongLong;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index a7a0057..3cf74bc 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -25,9 +25,9 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/IR/Type.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetParser.h"
#include <algorithm>
#include <memory>
using namespace clang;
@@ -185,6 +185,28 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
}
namespace {
+// CloudABI Target
+template <typename Target>
+class CloudABITargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__CloudABI__");
+ Builder.defineMacro("__ELF__");
+
+ // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
+ Builder.defineMacro("__STDC_ISO_10646__", "201206L");
+ Builder.defineMacro("__STDC_UTF_16__");
+ Builder.defineMacro("__STDC_UTF_32__");
+ }
+
+public:
+ CloudABITargetInfo(const llvm::Triple &Triple)
+ : OSTargetInfo<Target>(Triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
template<typename Target>
class DarwinTargetInfo : public OSTargetInfo<Target> {
protected:
@@ -364,8 +386,13 @@ protected:
DefineStd(Builder, "linux", Opts);
Builder.defineMacro("__gnu_linux__");
Builder.defineMacro("__ELF__");
- if (Triple.getEnvironment() == llvm::Triple::Android)
+ if (Triple.getEnvironment() == llvm::Triple::Android) {
Builder.defineMacro("__ANDROID__", "1");
+ unsigned Maj, Min, Rev;
+ Triple.getEnvironmentVersion(Maj, Min, Rev);
+ this->PlatformName = "android";
+ this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ }
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
@@ -473,6 +500,17 @@ protected:
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
+
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ Builder.defineMacro("__ARM_DWARF_EH__");
+ break;
+ }
}
public:
BitrigTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
@@ -526,6 +564,35 @@ public:
}
};
+template <typename Target>
+class PS4OSTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__FreeBSD__", "9");
+ Builder.defineMacro("__FreeBSD_cc_version", "900001");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__PS4__");
+ }
+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()) {
+ default:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ }
+ }
+};
+
// Solaris target
template<typename Target>
class SolarisTargetInfo : public OSTargetInfo<Target> {
@@ -574,7 +641,7 @@ protected:
if (Opts.RTTIData)
Builder.defineMacro("_CPPRTTI");
- if (Opts.Exceptions)
+ if (Opts.CXXExceptions)
Builder.defineMacro("_CPPUNWIND");
}
@@ -592,6 +659,9 @@ protected:
Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
// FIXME We cannot encode the revision information into 32-bits
Builder.defineMacro("_MSC_BUILD", Twine(1));
+
+ if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
+ Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
}
if (Opts.MicrosoftExt) {
@@ -647,8 +717,7 @@ public:
// RegParmMax is inherited from the underlying architecture
this->LongDoubleFormat = &llvm::APFloat::IEEEdouble;
if (Triple.getArch() == llvm::Triple::arm) {
- this->DescriptionString =
- "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
+ // Handled in ARM's setABI().
} else if (Triple.getArch() == llvm::Triple::x86) {
this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32-S128";
} else if (Triple.getArch() == llvm::Triple::x86_64) {
@@ -660,19 +729,12 @@ public:
this->DescriptionString = "e-p:32:32-i64:64";
}
}
- typename Target::CallingConvCheckResult checkCallingConvention(
- CallingConv CC) const override {
- return CC == CC_PnaclCall ? Target::CCCR_OK :
- Target::checkCallingConvention(CC);
- }
};
-} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// Specific target implementations.
//===----------------------------------------------------------------------===//
-namespace {
// PPC abstract base class
class PPCTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@@ -683,14 +745,23 @@ class PPCTargetInfo : public TargetInfo {
// Target cpu features.
bool HasVSX;
bool HasP8Vector;
+ bool HasP8Crypto;
+ bool HasDirectMove;
+ bool HasQPX;
+ bool HasHTM;
+ bool HasBPERMD;
+ bool HasExtDiv;
protected:
std::string ABI;
public:
PPCTargetInfo(const llvm::Triple &Triple)
- : TargetInfo(Triple), HasVSX(false), HasP8Vector(false) {
+ : TargetInfo(Triple), HasVSX(false), HasP8Vector(false),
+ HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
+ HasBPERMD(false), HasExtDiv(false) {
BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
+ SimdDefaultAlign = 128;
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble;
}
@@ -794,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;
@@ -924,6 +997,12 @@ public:
bool hasSjLjLowering() const override {
return true;
}
+
+ bool useFloat128ManglingForLongDouble() const override {
+ return LongDoubleWidth == 128 &&
+ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble &&
+ getTriple().isOSBinFormatELF();
+ }
};
const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
@@ -949,14 +1028,53 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
continue;
}
+ if (Feature == "bpermd") {
+ HasBPERMD = true;
+ continue;
+ }
+
+ if (Feature == "extdiv") {
+ HasExtDiv = true;
+ continue;
+ }
+
if (Feature == "power8-vector") {
HasP8Vector = true;
continue;
}
+ if (Feature == "crypto") {
+ HasP8Crypto = true;
+ continue;
+ }
+
+ if (Feature == "direct-move") {
+ HasDirectMove = true;
+ continue;
+ }
+
+ if (Feature == "qpx") {
+ HasQPX = true;
+ continue;
+ }
+
+ if (Feature == "htm") {
+ HasHTM = true;
+ continue;
+ }
+
// 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;
}
@@ -988,7 +1106,7 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
}
// ABI options.
- if (ABI == "elfv1")
+ if (ABI == "elfv1" || ABI == "elfv1-qpx")
Builder.defineMacro("_CALL_ELF", "1");
if (ABI == "elfv2")
Builder.defineMacro("_CALL_ELF", "2");
@@ -1106,6 +1224,18 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__VSX__");
if (HasP8Vector)
Builder.defineMacro("__POWER8_VECTOR__");
+ if (HasP8Crypto)
+ Builder.defineMacro("__CRYPTO__");
+ if (HasHTM)
+ Builder.defineMacro("__HTM__");
+ if (getTriple().getArch() == llvm::Triple::ppc64le ||
+ (defs & ArchDefinePwr8) || (CPU == "pwr8")) {
+ 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");
+ if (PointerWidth == 64)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ }
// FIXME: The following are not yet generated here by Clang, but are
// generated by GCC:
@@ -1144,9 +1274,33 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
.Default(false);
Features["qpx"] = (CPU == "a2q");
-
- if (!ABI.empty())
- Features[ABI] = true;
+ Features["crypto"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
+ .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 {
@@ -1154,9 +1308,48 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("powerpc", true)
.Case("vsx", HasVSX)
.Case("power8-vector", HasP8Vector)
+ .Case("crypto", HasP8Crypto)
+ .Case("direct-move", HasDirectMove)
+ .Case("qpx", HasQPX)
+ .Case("htm", HasHTM)
+ .Case("bpermd", HasBPERMD)
+ .Case("extdiv", HasExtDiv)
.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",
@@ -1259,9 +1452,7 @@ void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
Aliases = GCCRegAliases;
NumAliases = llvm::array_lengthof(GCCRegAliases);
}
-} // end anonymous namespace.
-namespace {
class PPC32TargetInfo : public PPCTargetInfo {
public:
PPC32TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) {
@@ -1293,11 +1484,9 @@ public:
return TargetInfo::PowerABIBuiltinVaList;
}
};
-} // end anonymous namespace.
// Note: ABI differences may eventually require us to have a separate
// TargetInfo for little endian.
-namespace {
class PPC64TargetInfo : public PPCTargetInfo {
public:
PPC64TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) {
@@ -1332,19 +1521,16 @@ 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 == "elfv2") {
+ if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
ABI = Name;
return true;
}
return false;
}
};
-} // end anonymous namespace.
-
-namespace {
class DarwinPPC32TargetInfo :
public DarwinTargetInfo<PPC32TargetInfo> {
public:
@@ -1372,9 +1558,7 @@ public:
DescriptionString = "E-m:o-i64:64-n32:64";
}
};
-} // end anonymous namespace.
-namespace {
static const unsigned NVPTXAddrSpaceMap[] = {
1, // opencl_global
3, // opencl_local
@@ -1396,6 +1580,7 @@ namespace {
GK_SM21,
GK_SM30,
GK_SM35,
+ GK_SM37,
} GPU;
public:
@@ -1431,6 +1616,9 @@ namespace {
case GK_SM35:
CUDAArchCode = "350";
break;
+ case GK_SM37:
+ CUDAArchCode = "370";
+ break;
default:
llvm_unreachable("Unhandled target CPU");
}
@@ -1483,6 +1671,7 @@ namespace {
.Case("sm_21", GK_SM21)
.Case("sm_30", GK_SM30)
.Case("sm_35", GK_SM35)
+ .Case("sm_37", GK_SM37)
.Default(GK_NONE);
return GPU != GK_NONE;
@@ -1510,26 +1699,25 @@ namespace {
public:
NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
PointerWidth = PointerAlign = 32;
- SizeType = PtrDiffType = TargetInfo::UnsignedInt;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = TargetInfo::SignedInt;
IntPtrType = TargetInfo::SignedInt;
DescriptionString = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64";
- }
+ }
};
class NVPTX64TargetInfo : public NVPTXTargetInfo {
public:
NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
PointerWidth = PointerAlign = 64;
- SizeType = PtrDiffType = TargetInfo::UnsignedLongLong;
- IntPtrType = TargetInfo::SignedLongLong;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = TargetInfo::SignedLong;
+ IntPtrType = TargetInfo::SignedLong;
DescriptionString = "e-i64:64-v16:16-v32:32-n16:32:64";
- }
+ }
};
-}
-
-namespace {
-static const unsigned R600AddrSpaceMap[] = {
+static const unsigned AMDGPUAddrSpaceMap[] = {
1, // opencl_global
3, // opencl_local
2, // opencl_constant
@@ -1555,10 +1743,11 @@ static const char *DescriptionStringSI =
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
-class R600TargetInfo : public TargetInfo {
+class AMDGPUTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
+ static const char * const GCCRegNames[];
- /// \brief The GPU profiles supported by the R600 target.
+ /// \brief The GPU profiles supported by the AMDGPU target.
enum GPUKind {
GK_NONE,
GK_R600,
@@ -1570,14 +1759,32 @@ class R600TargetInfo : public TargetInfo {
GK_NORTHERN_ISLANDS,
GK_CAYMAN,
GK_SOUTHERN_ISLANDS,
- GK_SEA_ISLANDS
+ GK_SEA_ISLANDS,
+ GK_VOLCANIC_ISLANDS
} GPU;
+ bool hasFP64:1;
+ bool hasFMAF:1;
+ bool hasLDEXPF:1;
+
public:
- R600TargetInfo(const llvm::Triple &Triple)
- : TargetInfo(Triple), GPU(GK_R600) {
- DescriptionString = DescriptionStringR600;
- AddrSpaceMap = &R600AddrSpaceMap;
+ AMDGPUTargetInfo(const llvm::Triple &Triple)
+ : TargetInfo(Triple) {
+
+ if (Triple.getArch() == llvm::Triple::amdgcn) {
+ DescriptionString = DescriptionStringSI;
+ GPU = GK_SOUTHERN_ISLANDS;
+ hasFP64 = true;
+ hasFMAF = true;
+ hasLDEXPF = true;
+ } else {
+ DescriptionString = DescriptionStringR600;
+ GPU = GK_R600;
+ hasFP64 = false;
+ hasFMAF = false;
+ hasLDEXPF = false;
+ }
+ AddrSpaceMap = &AMDGPUAddrSpaceMap;
UseAddrSpaceMapMangling = true;
}
@@ -1600,10 +1807,7 @@ public:
}
void getGCCRegNames(const char * const *&Names,
- unsigned &numNames) const override {
- Names = nullptr;
- numNames = 0;
- }
+ unsigned &NumNames) const override;
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {
@@ -1619,12 +1823,19 @@ public:
void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const override {
Records = BuiltinInfo;
- NumRecords = clang::R600::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ NumRecords = clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
Builder.defineMacro("__R600__");
+ if (hasFMAF)
+ Builder.defineMacro("__HAS_FMAF__");
+ if (hasLDEXPF)
+ Builder.defineMacro("__HAS_LDEXPF__");
+ if (hasFP64 && Opts.OpenCL) {
+ Builder.defineMacro("cl_khr_fp64");
+ }
}
BuiltinVaListKind getBuiltinVaListKind() const override {
@@ -1668,6 +1879,9 @@ public:
.Case("kaveri", GK_SEA_ISLANDS)
.Case("hawaii", GK_SEA_ISLANDS)
.Case("mullins", GK_SEA_ISLANDS)
+ .Case("tonga", GK_VOLCANIC_ISLANDS)
+ .Case("iceland", GK_VOLCANIC_ISLANDS)
+ .Case("carrizo", GK_VOLCANIC_ISLANDS)
.Default(GK_NONE);
if (GPU == GK_NONE) {
@@ -1682,16 +1896,26 @@ public:
case GK_EVERGREEN:
case GK_NORTHERN_ISLANDS:
DescriptionString = DescriptionStringR600;
+ hasFP64 = false;
+ hasFMAF = false;
+ hasLDEXPF = false;
break;
case GK_R600_DOUBLE_OPS:
case GK_R700_DOUBLE_OPS:
case GK_EVERGREEN_DOUBLE_OPS:
case GK_CAYMAN:
DescriptionString = DescriptionStringR600DoubleOps;
+ hasFP64 = true;
+ hasFMAF = true;
+ hasLDEXPF = false;
break;
case GK_SOUTHERN_ISLANDS:
case GK_SEA_ISLANDS:
+ case GK_VOLCANIC_ISLANDS:
DescriptionString = DescriptionStringSI;
+ hasFP64 = true;
+ hasFMAF = true;
+ hasLDEXPF = true;
break;
}
@@ -1699,15 +1923,70 @@ public:
}
};
-const Builtin::Info R600TargetInfo::BuiltinInfo[] = {
+const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{ #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#include "clang/Basic/BuiltinsR600.def"
+#include "clang/Basic/BuiltinsAMDGPU.def"
+};
+const char * const AMDGPUTargetInfo::GCCRegNames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+ "v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39",
+ "v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47",
+ "v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55",
+ "v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63",
+ "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
+ "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79",
+ "v80", "v81", "v82", "v83", "v84", "v85", "v86", "v87",
+ "v88", "v89", "v90", "v91", "v92", "v93", "v94", "v95",
+ "v96", "v97", "v98", "v99", "v100", "v101", "v102", "v103",
+ "v104", "v105", "v106", "v107", "v108", "v109", "v110", "v111",
+ "v112", "v113", "v114", "v115", "v116", "v117", "v118", "v119",
+ "v120", "v121", "v122", "v123", "v124", "v125", "v126", "v127",
+ "v128", "v129", "v130", "v131", "v132", "v133", "v134", "v135",
+ "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
+ "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151",
+ "v152", "v153", "v154", "v155", "v156", "v157", "v158", "v159",
+ "v160", "v161", "v162", "v163", "v164", "v165", "v166", "v167",
+ "v168", "v169", "v170", "v171", "v172", "v173", "v174", "v175",
+ "v176", "v177", "v178", "v179", "v180", "v181", "v182", "v183",
+ "v184", "v185", "v186", "v187", "v188", "v189", "v190", "v191",
+ "v192", "v193", "v194", "v195", "v196", "v197", "v198", "v199",
+ "v200", "v201", "v202", "v203", "v204", "v205", "v206", "v207",
+ "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
+ "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223",
+ "v224", "v225", "v226", "v227", "v228", "v229", "v230", "v231",
+ "v232", "v233", "v234", "v235", "v236", "v237", "v238", "v239",
+ "v240", "v241", "v242", "v243", "v244", "v245", "v246", "v247",
+ "v248", "v249", "v250", "v251", "v252", "v253", "v254", "v255",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+ "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39",
+ "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47",
+ "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55",
+ "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63",
+ "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71",
+ "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79",
+ "s80", "s81", "s82", "s83", "s84", "s85", "s86", "s87",
+ "s88", "s89", "s90", "s91", "s92", "s93", "s94", "s95",
+ "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
+ "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111",
+ "s112", "s113", "s114", "s115", "s116", "s117", "s118", "s119",
+ "s120", "s121", "s122", "s123", "s124", "s125", "s126", "s127"
+ "exec", "vcc", "scc", "m0", "flat_scr", "exec_lo", "exec_hi",
+ "vcc_lo", "vcc_hi", "flat_scr_lo", "flat_scr_hi"
};
-} // end anonymous namespace
+void AMDGPUTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
-namespace {
// Namespace for x86 abstract base class
const Builtin::Info BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
@@ -1986,6 +2265,7 @@ public:
Names = AddlRegNames;
NumNames = llvm::array_lengthof(AddlRegNames);
}
+ bool validateCpuSupports(StringRef Name) const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
@@ -2020,7 +2300,9 @@ public:
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
StringRef getABI() const override {
- if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
+ return "avx512";
+ else if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
return "avx";
else if (getTriple().getArch() == llvm::Triple::x86 &&
MMX3DNowLevel == NoMMX3DNow)
@@ -2496,12 +2778,11 @@ void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled) {
- // FIXME: This *really* should not be here. We need some way of translating
- // options into llvm subtarget features.
- if (Name == "sse4")
- Name = "sse4.2";
-
- Features[Name] = Enabled;
+ // This is a bit of a hack to deal with the sse4 target feature when used
+ // as part of the target attribute. We handle sse4 correctly everywhere
+ // else. See below for more information on how we handle the sse4 options.
+ if (Name != "sse4")
+ Features[Name] = Enabled;
if (Name == "mmx") {
setMMXLevel(Features, MMX, Enabled);
@@ -2552,6 +2833,15 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
} else if (Name == "sha") {
if (Enabled)
setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse4") {
+ // We can get here via the __target__ attribute since that's not controlled
+ // via the -msse4/-mno-sse4 command line alias. Handle this the same way
+ // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if
+ // disabled.
+ if (Enabled)
+ setSSELevel(Features, SSE42, Enabled);
+ else
+ setSSELevel(Features, SSE41, Enabled);
}
}
@@ -2748,6 +3038,9 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
Features.erase(it);
else if (SSELevel > NoSSE)
MMX3DNowLevel = std::max(MMX3DNowLevel, MMX);
+
+ SimdDefaultAlign =
+ (getABI() == "avx512") ? 512 : (getABI() == "avx") ? 256 : 128;
return true;
}
@@ -3112,6 +3405,33 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
+// We can't use a generic validation scheme for the features accepted here
+// versus subtarget features accepted in the target attribute because the
+// bitfield structure that's initialized in the runtime only supports the
+// below currently rather than the full range of subtarget features. (See
+// X86TargetInfo::hasFeature for a somewhat comprehensive list).
+bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+ .Case("cmov", true)
+ .Case("mmx", true)
+ .Case("popcnt", true)
+ .Case("sse", true)
+ .Case("sse2", true)
+ .Case("sse3", true)
+ .Case("sse4.1", true)
+ .Case("sse4.2", true)
+ .Case("avx", true)
+ .Case("avx2", true)
+ .Case("sse4a", true)
+ .Case("fma4", true)
+ .Case("xop", true)
+ .Case("fma", true)
+ .Case("avx512f", true)
+ .Case("bmi", true)
+ .Case("bmi2", true)
+ .Default(false);
+}
+
bool
X86TargetInfo::validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const {
@@ -3236,9 +3556,7 @@ X86TargetInfo::convertConstraint(const char *&Constraint) const {
return std::string(1, *Constraint);
}
}
-} // end anonymous namespace
-namespace {
// X86-32 generic target
class X86_32TargetInfo : public X86TargetInfo {
public:
@@ -3293,9 +3611,7 @@ public:
return X86TargetInfo::validateOperandSize(Constraint, Size);
}
};
-} // end anonymous namespace
-namespace {
class NetBSDI386TargetInfo : public NetBSDTargetInfo<X86_32TargetInfo> {
public:
NetBSDI386TargetInfo(const llvm::Triple &Triple)
@@ -3311,9 +3627,7 @@ public:
return 1;
}
};
-} // end anonymous namespace
-namespace {
class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> {
public:
OpenBSDI386TargetInfo(const llvm::Triple &Triple)
@@ -3323,9 +3637,7 @@ public:
PtrDiffType = SignedLong;
}
};
-} // end anonymous namespace
-namespace {
class BitrigI386TargetInfo : public BitrigTargetInfo<X86_32TargetInfo> {
public:
BitrigI386TargetInfo(const llvm::Triple &Triple)
@@ -3335,9 +3647,7 @@ public:
PtrDiffType = SignedLong;
}
};
-} // end anonymous namespace
-namespace {
class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> {
public:
DarwinI386TargetInfo(const llvm::Triple &Triple)
@@ -3353,9 +3663,7 @@ public:
}
};
-} // end anonymous namespace
-namespace {
// x86-32 Windows target
class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> {
public:
@@ -3365,8 +3673,9 @@ public:
DoubleAlign = LongLongAlign = 64;
bool IsWinCOFF =
getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
- DescriptionString = IsWinCOFF ? "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
- : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-S32";
+ DescriptionString = IsWinCOFF
+ ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+ : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -3394,11 +3703,8 @@ public:
};
} // end anonymous namespace
-static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW32__");
-
- // Mingw defines __declspec(a) to __attribute__((a)). Clang supports
+static void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
+ // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang supports
// __declspec natively under -fms-extensions, but we define a no-op __declspec
// macro anyway for pre-processor compatibility.
if (Opts.MicrosoftExt)
@@ -3421,6 +3727,12 @@ static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
}
}
+static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+ addCygMingDefines(Opts, Builder);
+}
+
namespace {
// x86-32 MinGW target
class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
@@ -3436,9 +3748,7 @@ public:
addMinGWDefines(Opts, Builder);
}
};
-} // end anonymous namespace
-namespace {
// x86-32 Cygwin target
class CygwinX86_32TargetInfo : public X86_32TargetInfo {
public:
@@ -3447,7 +3757,7 @@ public:
TLSSupported = false;
WCharType = UnsignedShort;
DoubleAlign = LongLongAlign = 64;
- DescriptionString = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32";
+ DescriptionString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -3455,14 +3765,13 @@ public:
Builder.defineMacro("_X86_");
Builder.defineMacro("__CYGWIN__");
Builder.defineMacro("__CYGWIN32__");
+ addCygMingDefines(Opts, Builder);
DefineStd(Builder, "unix", Opts);
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
};
-} // end anonymous namespace
-namespace {
// x86-32 Haiku target
class HaikuX86_32TargetInfo : public X86_32TargetInfo {
public:
@@ -3481,7 +3790,6 @@ public:
Builder.defineMacro("__HAIKU__");
}
};
-} // end anonymous namespace
// RTEMS Target
template<typename Target>
@@ -3518,7 +3826,6 @@ public:
}
};
-namespace {
// x86-32 RTEMS target
class RTEMSX86_32TargetInfo : public X86_32TargetInfo {
public:
@@ -3535,14 +3842,14 @@ public:
Builder.defineMacro("__rtems__");
}
};
-} // end anonymous namespace
-namespace {
// x86-64 generic target
class X86_64TargetInfo : public X86TargetInfo {
public:
X86_64TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple) {
const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
LongDoubleWidth = 128;
LongDoubleAlign = 128;
@@ -3557,9 +3864,10 @@ public:
RegParmMax = 6;
// Pointers are 32-bit in x32.
- DescriptionString = (IsX32)
- ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
- : "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
+ DescriptionString = IsX32 ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
+ : IsWinCOFF
+ ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+ : "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
// Use fpret only for long double.
RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
@@ -3595,9 +3903,7 @@ public:
// for x32 we need it here explicitly
bool hasInt128Type() const override { return true; }
};
-} // end anonymous namespace
-namespace {
// x86-64 Windows target
class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> {
public:
@@ -3613,24 +3919,34 @@ public:
IntPtrType = SignedLongLong;
this->UserLabelPrefix = "";
}
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder);
Builder.defineMacro("_WIN64");
}
+
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- return (CC == CC_C ||
- CC == CC_X86VectorCall ||
- CC == CC_IntelOclBicc ||
- CC == CC_X86_64SysV) ? CCCR_OK : CCCR_Warning;
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_X86VectorCall:
+ case CC_IntelOclBicc:
+ case CC_X86_64SysV:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
}
};
-} // end anonymous namespace
-namespace {
// x86-64 Windows Visual Studio target
class MicrosoftX86_64TargetInfo : public WindowsX86_64TargetInfo {
public:
@@ -3647,9 +3963,7 @@ public:
Builder.defineMacro("_M_AMD64");
}
};
-} // end anonymous namespace
-namespace {
// x86-64 MinGW target
class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
public:
@@ -3667,9 +3981,7 @@ public:
Builder.defineMacro("__SEH__");
}
};
-} // end anonymous namespace
-namespace {
class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
public:
DarwinX86_64TargetInfo(const llvm::Triple &Triple)
@@ -3683,9 +3995,7 @@ public:
DescriptionString = "e-m:o-i64:64-f80:128-n8:16:32:64-S128";
}
};
-} // end anonymous namespace
-namespace {
class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> {
public:
OpenBSDX86_64TargetInfo(const llvm::Triple &Triple)
@@ -3694,9 +4004,7 @@ public:
Int64Type = SignedLongLong;
}
};
-} // end anonymous namespace
-namespace {
class BitrigX86_64TargetInfo : public BitrigTargetInfo<X86_64TargetInfo> {
public:
BitrigX86_64TargetInfo(const llvm::Triple &Triple)
@@ -3705,10 +4013,7 @@ public:
Int64Type = SignedLongLong;
}
};
-}
-
-namespace {
class ARMTargetInfo : public TargetInfo {
// Possible FPU choices.
enum FPUMode {
@@ -3800,8 +4105,9 @@ class ARMTargetInfo : public TargetInfo {
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
const llvm::Triple &T = getTriple();
- // size_t is unsigned long on MachO-derived environments and NetBSD.
- if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD)
+ // size_t is unsigned long on MachO-derived environments, NetBSD and Bitrig.
+ if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
+ T.getOS() == llvm::Triple::Bitrig)
SizeType = UnsignedLong;
else
SizeType = UnsignedInt;
@@ -3831,16 +4137,18 @@ class ARMTargetInfo : public TargetInfo {
BigEndian ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
: "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64";
} else if (T.isOSWindows()) {
- // FIXME: this is invalid for WindowsCE
assert(!BigEndian && "Windows on ARM does not support big endian");
DescriptionString = "e"
- "-m:e"
+ "-m:w"
"-p:32:32"
"-i64:64"
"-v128:64:128"
"-a:0:32"
"-n32"
"-S64";
+ } else if (T.isOSNaCl()) {
+ assert(!BigEndian && "NaCl on ARM does not support big endian");
+ DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
} else {
DescriptionString =
BigEndian ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
@@ -3965,7 +4273,9 @@ public:
// zero length bitfield.
UseZeroLengthBitfieldAlignment = true;
}
+
StringRef getABI() const override { return ABI; }
+
bool setABI(const std::string &Name) override {
ABI = Name;
@@ -3984,8 +4294,13 @@ public:
return false;
}
+ // 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") {
@@ -4002,28 +4317,19 @@ public:
Features["neon"] = true;
Features["hwdiv"] = true;
Features["hwdiv-arm"] = true;
- } else if (CPU == "cyclone") {
- Features["v8fp"] = true;
- Features["neon"] = true;
- Features["hwdiv"] = true;
- Features["hwdiv-arm"] = true;
- } else if (CPU == "cortex-a53" || CPU == "cortex-a57") {
+ } else if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" ||
+ CPU == "cortex-a72") {
Features["fp-armv8"] = true;
Features["neon"] = true;
Features["hwdiv"] = true;
Features["hwdiv-arm"] = true;
Features["crc"] = true;
Features["crypto"] = true;
- } else if (CPU == "cortex-r5" ||
- // Enable the hwdiv extension for all v8a AArch32 cores by
- // default.
- ArchName == "armv8a" || ArchName == "armv8" ||
- ArchName == "armebv8a" || ArchName == "armebv8" ||
- ArchName == "thumbv8a" || ArchName == "thumbv8" ||
- ArchName == "thumbebv8a" || ArchName == "thumbebv8") {
+ } 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") {
+ } else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" ||
+ CPU == "sc300" || CPU == "cortex-r4" || CPU == "cortex-r4f") {
Features["hwdiv"] = true;
}
}
@@ -4036,6 +4342,9 @@ public:
SoftFloat = SoftFloatABI = false;
HWDiv = 0;
+ // This does not diagnose illegal cases like having both
+ // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
+ uint32_t HW_FP_remove = 0;
for (const auto &Feature : Features) {
if (Feature == "+soft-float") {
SoftFloat = true;
@@ -4043,19 +4352,19 @@ public:
SoftFloatABI = true;
} else if (Feature == "+vfp2") {
FPU |= VFP2FPU;
- HW_FP = HW_FP_SP | HW_FP_DP;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+vfp3") {
FPU |= VFP3FPU;
- HW_FP = HW_FP_SP | HW_FP_DP;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+vfp4") {
FPU |= VFP4FPU;
- HW_FP = HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
} else if (Feature == "+fp-armv8") {
FPU |= FPARMV8;
- HW_FP = HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
} else if (Feature == "+neon") {
FPU |= NeonFPU;
- HW_FP = HW_FP_SP | HW_FP_DP;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+hwdiv") {
HWDiv |= HWDivThumb;
} else if (Feature == "+hwdiv-arm") {
@@ -4065,9 +4374,10 @@ public:
} else if (Feature == "+crypto") {
Crypto = 1;
} else if (Feature == "+fp-only-sp") {
- HW_FP &= ~HW_FP_DP;
+ HW_FP_remove |= HW_FP_DP | HW_FP_HP;
}
}
+ HW_FP &= ~HW_FP_remove;
if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
@@ -4080,12 +4390,10 @@ public:
Features.push_back("-neonfp");
// Remove front-end specific options which the backend handles differently.
- const StringRef FrontEndFeatures[] = { "+soft-float", "+soft-float-abi" };
- for (const auto &FEFeature : FrontEndFeatures) {
- auto Feature = std::find(Features.begin(), Features.end(), FEFeature);
- if (Feature != Features.end())
- Features.erase(Feature);
- }
+ auto Feature =
+ std::find(Features.begin(), Features.end(), "+soft-float-abi");
+ if (Feature != Features.end())
+ Features.erase(Feature);
return true;
}
@@ -4100,45 +4408,71 @@ public:
.Case("hwdiv-arm", HWDiv & HWDivARM)
.Default(false);
}
- // FIXME: Should we actually have some table instead of these switches?
- static const char *getCPUDefineSuffix(StringRef Name) {
- return llvm::StringSwitch<const char *>(Name)
- .Cases("arm8", "arm810", "4")
- .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110",
- "4")
- .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "arm720t", "arm9", "4T")
- .Cases("arm9tdmi", "arm920", "arm920t", "arm922t", "arm940t", "4T")
- .Case("ep9312", "4T")
- .Cases("arm10tdmi", "arm1020t", "5T")
- .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "5TE")
- .Case("arm926ej-s", "5TEJ")
- .Cases("arm10e", "arm1020e", "arm1022e", "5TE")
- .Cases("xscale", "iwmmxt", "5TE")
- .Case("arm1136j-s", "6J")
- .Cases("arm1176jz-s", "arm1176jzf-s", "6ZK")
- .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K")
- .Cases("arm1156t2-s", "arm1156t2f-s", "6T2")
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "7A")
- .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait",
- "7A")
- .Cases("cortex-r4", "cortex-r5", "7R")
- .Case("swift", "7S")
- .Case("cyclone", "8A")
- .Case("cortex-m3", "7M")
- .Cases("cortex-m4", "cortex-m7", "7EM")
- .Case("cortex-m0", "6M")
- .Cases("cortex-a53", "cortex-a57", "8A")
- .Default(nullptr);
- }
- static const char *getCPUProfile(StringRef Name) {
- return llvm::StringSwitch<const char *>(Name)
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "A")
- .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait",
- "A")
- .Cases("cortex-a53", "cortex-a57", "A")
- .Cases("cortex-m3", "cortex-m4", "cortex-m0", "cortex-m7", "M")
- .Cases("cortex-r4", "cortex-r5", "R")
- .Default("");
+ 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:
+ return llvm::ARMTargetParser::getCPUAttr(ArchKind);
+ case llvm::ARM::AK_ARMV6M:
+ case llvm::ARM::AK_ARMV6SM:
+ return "6M";
+ case llvm::ARM::AK_ARMV7:
+ case llvm::ARM::AK_ARMV7A:
+ case llvm::ARM::AK_ARMV7S:
+ return "7A";
+ case llvm::ARM::AK_ARMV7R:
+ return "7R";
+ case llvm::ARM::AK_ARMV7M:
+ return "7M";
+ case llvm::ARM::AK_ARMV7EM:
+ return "7EM";
+ case llvm::ARM::AK_ARMV8A:
+ return "8A";
+ case llvm::ARM::AK_ARMV8_1A:
+ return "8_1A";
+ }
+ }
+ 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:
+ return "R";
+ case llvm::ARM::PK_M:
+ return "M";
+ default:
+ return "";
+ }
}
bool setCPU(const std::string &Name) override {
if (!getCPUDefineSuffix(Name))
@@ -4165,6 +4499,7 @@ public:
// 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,
@@ -4499,8 +4834,8 @@ class ARMleTargetInfo : public ARMTargetInfo {
public:
ARMleTargetInfo(const llvm::Triple &Triple)
: ARMTargetInfo(Triple, false) { }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEL__");
ARMTargetInfo::getTargetDefines(Opts, Builder);
}
@@ -4510,16 +4845,14 @@ class ARMbeTargetInfo : public ARMTargetInfo {
public:
ARMbeTargetInfo(const llvm::Triple &Triple)
: ARMTargetInfo(Triple, true) { }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEB__");
Builder.defineMacro("__ARM_BIG_ENDIAN");
ARMTargetInfo::getTargetDefines(Opts, Builder);
}
};
-} // end anonymous namespace.
-namespace {
class WindowsARMTargetInfo : public WindowsTargetInfo<ARMleTargetInfo> {
const llvm::Triple Triple;
public:
@@ -4585,10 +4918,7 @@ public:
WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
}
};
-}
-
-namespace {
class DarwinARMTargetInfo :
public DarwinTargetInfo<ARMleTargetInfo> {
protected:
@@ -4610,10 +4940,7 @@ public:
TheCXXABI.set(TargetCXXABI::iOS);
}
};
-} // end anonymous namespace.
-
-namespace {
class AArch64TargetInfo : public TargetInfo {
virtual void setDescriptionString() = 0;
static const TargetInfo::GCCRegAlias GCCRegAliases[];
@@ -4655,13 +4982,20 @@ public:
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
- LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
+ // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
+ // contributes to the alignment of the containing aggregate in the same way
+ // a plain (non bit-field) member of that type would, without exception for
+ // zero-sized or anonymous bit-fields."
+ UseBitFieldTypeAlignment = true;
+ UseZeroLengthBitfieldAlignment = true;
+
// AArch64 targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericAArch64);
}
@@ -4678,14 +5012,14 @@ public:
bool setCPU(const std::string &Name) override {
bool CPUKnown = llvm::StringSwitch<bool>(Name)
.Case("generic", true)
- .Cases("cortex-a53", "cortex-a57", true)
+ .Cases("cortex-a53", "cortex-a57", "cortex-a72", true)
.Case("cyclone", true)
.Default(false);
return CPUKnown;
}
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
// Target identification.
Builder.defineMacro("__aarch64__");
@@ -4742,10 +5076,16 @@ public:
if (Crypto)
Builder.defineMacro("__ARM_FEATURE_CRYPTO");
+
+ // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
+ 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");
}
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
+ void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const override {
Records = BuiltinInfo;
NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
}
@@ -4781,14 +5121,13 @@ public:
return TargetInfo::AArch64ABIBuiltinVaList;
}
- virtual void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ void getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const override;
+ void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const override;
- virtual bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
default:
return false;
@@ -4963,9 +5302,7 @@ public:
AArch64TargetInfo::getTargetDefines(Opts, Builder);
}
};
-} // end anonymous namespace.
-namespace {
class DarwinAArch64TargetInfo : public DarwinTargetInfo<AArch64leTargetInfo> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
@@ -4988,7 +5325,7 @@ public:
WCharType = SignedInt;
UseSignedCharForObjCBool = false;
- LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
TheCXXABI.set(TargetCXXABI::iOS64);
@@ -4998,9 +5335,7 @@ public:
return TargetInfo::CharPtrBuiltinVaList;
}
};
-} // end anonymous namespace
-namespace {
// Hexagon abstract base class
class HexagonTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@@ -5149,24 +5484,25 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
ALL_LANGUAGES },
#include "clang/Basic/BuiltinsHexagon.def"
};
-}
-
-namespace {
// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
class SparcTargetInfo : public TargetInfo {
static const TargetInfo::GCCRegAlias GCCRegAliases[];
static const char * const GCCRegNames[];
bool SoftFloat;
public:
- SparcTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {}
+ SparcTargetInfo(const llvm::Triple &Triple)
+ : TargetInfo(Triple), SoftFloat(false) {}
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override {
- SoftFloat = false;
- for (unsigned i = 0, e = Features.size(); i != e; ++i)
- if (Features[i] == "+soft-float")
- SoftFloat = true;
+ // The backend doesn't actually handle soft float yet, but in case someone
+ // is using the support for the front end continue to support it.
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float");
+ if (Feature != Features.end()) {
+ SoftFloat = true;
+ Features.erase(Feature);
+ }
return true;
}
void getTargetDefines(const LangOptions &Opts,
@@ -5276,6 +5612,16 @@ class SparcV8TargetInfo : public SparcTargetInfo {
public:
SparcV8TargetInfo(const llvm::Triple &Triple) : SparcTargetInfo(Triple) {
DescriptionString = "E-m:e-p:32:32-i64:64-f128:64-n32-S64";
+ // NetBSD uses long (same as llvm default); everyone else uses int.
+ if (getTriple().getOS() == llvm::Triple::NetBSD) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ } else {
+ SizeType = UnsignedInt;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ }
}
void getTargetDefines(const LangOptions &Opts,
@@ -5285,6 +5631,15 @@ public:
}
};
+// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
+class SparcV8elTargetInfo : public SparcV8TargetInfo {
+ public:
+ SparcV8elTargetInfo(const llvm::Triple &Triple) : SparcV8TargetInfo(Triple) {
+ DescriptionString = "e-m:e-p:32:32-i64:64-f128:64-n32-S64";
+ BigEndian = false;
+ }
+};
+
// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
class SparcV9TargetInfo : public SparcTargetInfo {
public:
@@ -5339,25 +5694,18 @@ public:
}
};
-} // end anonymous namespace.
-
-namespace {
-class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
-public:
- SolarisSparcV8TargetInfo(const llvm::Triple &Triple)
- : SolarisTargetInfo<SparcV8TargetInfo>(Triple) {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- }
-};
-} // end anonymous namespace.
-
-namespace {
class SystemZTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
static const char *const GCCRegNames[];
+ std::string CPU;
+ bool HasTransactionalExecution;
+ bool HasVector;
public:
- SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ SystemZTargetInfo(const llvm::Triple &Triple)
+ : TargetInfo(Triple), CPU("z10"), HasTransactionalExecution(false), HasVector(false) {
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
TLSSupported = true;
IntWidth = IntAlign = 32;
LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
@@ -5365,6 +5713,7 @@ public:
LongDoubleWidth = 128;
LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ DefaultAlignForAttributeAligned = 64;
MinGlobalAlign = 16;
DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
@@ -5375,12 +5724,13 @@ public:
Builder.defineMacro("__s390x__");
Builder.defineMacro("__zarch__");
Builder.defineMacro("__LONG_DOUBLE_128__");
+ if (HasTransactionalExecution)
+ Builder.defineMacro("__HTM__");
}
void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const override {
- // FIXME: Implement.
- Records = nullptr;
- NumRecords = 0;
+ Records = BuiltinInfo;
+ NumRecords = clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin;
}
void getGCCRegNames(const char *const *&Names,
@@ -5401,16 +5751,66 @@ public:
return TargetInfo::SystemZBuiltinVaList;
}
bool setCPU(const std::string &Name) override {
+ CPU = Name;
bool CPUKnown = llvm::StringSwitch<bool>(Name)
.Case("z10", true)
.Case("z196", true)
.Case("zEC12", true)
+ .Case("z13", true)
.Default(false);
- // No need to store the CPU yet. There aren't any CPU-specific
- // macros to define.
return CPUKnown;
}
+ void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
+ if (CPU == "zEC12")
+ Features["transactional-execution"] = true;
+ if (CPU == "z13") {
+ Features["transactional-execution"] = true;
+ Features["vector"] = true;
+ }
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ HasTransactionalExecution = false;
+ for (unsigned i = 0, e = Features.size(); i != e; ++i) {
+ if (Features[i] == "+transactional-execution")
+ HasTransactionalExecution = true;
+ if (Features[i] == "+vector")
+ HasVector = true;
+ }
+ // If we use the vector ABI, vector types are 64-bit aligned.
+ if (HasVector) {
+ MaxVectorAlign = 64;
+ DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
+ "-v128:64-a:8:16-n32:64";
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("systemz", true)
+ .Case("htm", HasTransactionalExecution)
+ .Case("vx", HasVector)
+ .Default(false);
+ }
+
+ StringRef getABI() const override {
+ if (HasVector)
+ return "vector";
+ return "";
+ }
+
+ bool useFloat128ManglingForLongDouble() const override {
+ return true;
+ }
+};
+
+const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+#include "clang/Basic/BuiltinsSystemZ.def"
};
const char *const SystemZTargetInfo::GCCRegNames[] = {
@@ -5454,9 +5854,7 @@ validateAsmConstraint(const char *&Name,
return true;
}
}
-}
-namespace {
class MSP430TargetInfo : public TargetInfo {
static const char * const GCCRegNames[];
public:
@@ -5531,9 +5929,6 @@ namespace {
Names = GCCRegNames;
NumNames = llvm::array_lengthof(GCCRegNames);
}
-}
-
-namespace {
// LLVM and Clang cannot be used directly to output native binaries for
// target, but is used to compile C code to llvm bitcode with correct
@@ -5611,9 +6006,61 @@ namespace {
void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const override {}
};
-}
-namespace {
+class BPFTargetInfo : public TargetInfo {
+public:
+ BPFTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+ RegParmMax = 5;
+ if (Triple.getArch() == llvm::Triple::bpfeb) {
+ BigEndian = true;
+ DescriptionString = "E-m:e-p:64:64-i64:64-n32:64-S128";
+ } else {
+ BigEndian = false;
+ DescriptionString = "e-m:e-p:64:64-i64:64-n32:64-S128";
+ }
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 64;
+ TLSSupported = false;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "bpf", Opts);
+ Builder.defineMacro("__BPF__");
+ }
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "bpf";
+ }
+
+ void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const override {}
+ const char *getClobbers() const override {
+ return "";
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+ void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const override {
+ Names = nullptr;
+ NumNames = 0;
+ }
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+ void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const override {
+ Aliases = nullptr;
+ NumAliases = 0;
+ }
+};
+
class MipsTargetInfoBase : public TargetInfo {
virtual void setDescriptionString() = 0;
@@ -5652,6 +6099,10 @@ public:
return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
}
+ bool isNan2008() const override {
+ return IsNan2008;
+ }
+
StringRef getABI() const override { return ABI; }
bool setCPU(const std::string &Name) override {
bool IsMips32 = getTriple().getArch() == llvm::Triple::mips ||
@@ -5665,23 +6116,19 @@ public:
.Case("mips5", true)
.Case("mips32", IsMips32)
.Case("mips32r2", IsMips32)
+ .Case("mips32r3", IsMips32)
+ .Case("mips32r5", IsMips32)
.Case("mips32r6", IsMips32)
.Case("mips64", true)
.Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
.Case("mips64r6", true)
.Case("octeon", true)
.Default(false);
}
const std::string& getCPU() const { return CPU; }
void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
- // The backend enables certain ABI's by default according to the
- // architecture.
- // Disable both possible defaults so that we don't end up with multiple
- // ABI's selected and trigger an assertion.
- Features["o32"] = false;
- Features["n64"] = false;
-
- Features[ABI] = true;
if (CPU == "octeon")
Features["mips64r2"] = Features["cnmips"] = true;
else
@@ -5818,7 +6265,28 @@ public:
case 'R': // An address that can be used in a non-macro load or store
Info.setAllowsMemory();
return true;
+ case 'Z':
+ if (Name[1] == 'C') { // An address usable by ll, and sc.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'Z'.
+ return true;
+ }
+ return false;
+ }
+ }
+
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'Z': // Two-character constraint; add "^" hint for later parsing.
+ if (Constraint[1] == 'C') {
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ return R;
+ }
+ break;
}
+ return TargetInfo::convertConstraint(Constraint);
}
const char *getClobbers() const override {
@@ -5882,12 +6350,6 @@ public:
IsNan2008 = false;
}
- // Remove front-end specific options.
- std::vector<std::string>::iterator it =
- std::find(Features.begin(), Features.end(), "+soft-float");
- if (it != Features.end())
- Features.erase(it);
-
setDescriptionString();
return true;
@@ -5938,6 +6400,10 @@ public:
Builder.defineMacro("__mips_isa_rev", "1");
else if (CPUStr == "mips32r2")
Builder.defineMacro("__mips_isa_rev", "2");
+ else if (CPUStr == "mips32r3")
+ Builder.defineMacro("__mips_isa_rev", "3");
+ else if (CPUStr == "mips32r5")
+ Builder.defineMacro("__mips_isa_rev", "5");
else if (CPUStr == "mips32r6")
Builder.defineMacro("__mips_isa_rev", "6");
@@ -6087,6 +6553,10 @@ public:
Builder.defineMacro("__mips_isa_rev", "1");
else if (CPUStr == "mips64r2")
Builder.defineMacro("__mips_isa_rev", "2");
+ else if (CPUStr == "mips64r3")
+ Builder.defineMacro("__mips_isa_rev", "3");
+ else if (CPUStr == "mips64r5")
+ Builder.defineMacro("__mips_isa_rev", "5");
else if (CPUStr == "mips64r6")
Builder.defineMacro("__mips_isa_rev", "6");
@@ -6185,9 +6655,7 @@ public:
Mips64TargetInfoBase::getTargetDefines(Opts, Builder);
}
};
-} // end anonymous namespace.
-namespace {
class PNaClTargetInfo : public TargetInfo {
public:
PNaClTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
@@ -6252,9 +6720,20 @@ void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
Aliases = nullptr;
NumAliases = 0;
}
-} // end anonymous namespace.
-namespace {
+// 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[];
@@ -6359,6 +6838,15 @@ namespace {
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ return (CC == CC_SpirFunction ||
+ CC == CC_SpirKernel) ? CCCR_OK : CCCR_Warning;
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_SpirFunction;
+ }
};
@@ -6392,9 +6880,7 @@ namespace {
DefineStd(Builder, "SPIR64", Opts);
}
};
-}
-namespace {
class XCoreTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
public:
@@ -6460,6 +6946,30 @@ const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = {
};
} // end anonymous namespace.
+namespace {
+// x86_32 Android target
+class AndroidX86_32TargetInfo : public LinuxTargetInfo<X86_32TargetInfo> {
+public:
+ AndroidX86_32TargetInfo(const llvm::Triple &Triple)
+ : LinuxTargetInfo<X86_32TargetInfo>(Triple) {
+ SuitableAlign = 32;
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86_64 Android target
+class AndroidX86_64TargetInfo : public LinuxTargetInfo<X86_64TargetInfo> {
+public:
+ AndroidX86_64TargetInfo(const llvm::Triple &Triple)
+ : LinuxTargetInfo<X86_64TargetInfo>(Triple) {
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ }
+};
+} // end anonymous namespace
+
//===----------------------------------------------------------------------===//
// Driver code
@@ -6562,6 +7072,10 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new ARMbeTargetInfo(Triple);
}
+ case llvm::Triple::bpfeb:
+ case llvm::Triple::bpfel:
+ return new BPFTargetInfo(Triple);
+
case llvm::Triple::msp430:
return new MSP430TargetInfo(Triple);
@@ -6590,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);
}
@@ -6629,10 +7143,10 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
case llvm::Triple::le32:
switch (os) {
- case llvm::Triple::NaCl:
- return new NaClTargetInfo<PNaClTargetInfo>(Triple);
- default:
- return nullptr;
+ case llvm::Triple::NaCl:
+ return new NaClTargetInfo<PNaClTargetInfo>(Triple);
+ default:
+ return nullptr;
}
case llvm::Triple::le64:
@@ -6689,14 +7203,14 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
case llvm::Triple::amdgcn:
case llvm::Triple::r600:
- return new R600TargetInfo(Triple);
+ return new AMDGPUTargetInfo(Triple);
case llvm::Triple::sparc:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<SparcV8TargetInfo>(Triple);
case llvm::Triple::Solaris:
- return new SolarisSparcV8TargetInfo(Triple);
+ return new SolarisTargetInfo<SparcV8TargetInfo>(Triple);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<SparcV8TargetInfo>(Triple);
case llvm::Triple::OpenBSD:
@@ -6707,6 +7221,21 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new SparcV8TargetInfo(Triple);
}
+ // The 'sparcel' architecture copies all the above cases except for Solaris.
+ case llvm::Triple::sparcel:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SparcV8elTargetInfo>(Triple);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<SparcV8elTargetInfo>(Triple);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<SparcV8elTargetInfo>(Triple);
+ case llvm::Triple::RTEMS:
+ return new RTEMSTargetInfo<SparcV8elTargetInfo>(Triple);
+ default:
+ return new SparcV8elTargetInfo(Triple);
+ }
+
case llvm::Triple::sparcv9:
switch (os) {
case llvm::Triple::Linux:
@@ -6739,8 +7268,16 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new DarwinI386TargetInfo(Triple);
switch (os) {
- case llvm::Triple::Linux:
- return new LinuxTargetInfo<X86_32TargetInfo>(Triple);
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<X86_32TargetInfo>(Triple);
+ case llvm::Triple::Linux: {
+ switch (Triple.getEnvironment()) {
+ default:
+ return new LinuxTargetInfo<X86_32TargetInfo>(Triple);
+ case llvm::Triple::Android:
+ return new AndroidX86_32TargetInfo(Triple);
+ }
+ }
case llvm::Triple::DragonFly:
return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(Triple);
case llvm::Triple::NetBSD:
@@ -6785,8 +7322,16 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new DarwinX86_64TargetInfo(Triple);
switch (os) {
- case llvm::Triple::Linux:
- return new LinuxTargetInfo<X86_64TargetInfo>(Triple);
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<X86_64TargetInfo>(Triple);
+ case llvm::Triple::Linux: {
+ switch (Triple.getEnvironment()) {
+ default:
+ return new LinuxTargetInfo<X86_64TargetInfo>(Triple);
+ case llvm::Triple::Android:
+ return new AndroidX86_64TargetInfo(Triple);
+ }
+ }
case llvm::Triple::DragonFly:
return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(Triple);
case llvm::Triple::NetBSD:
@@ -6813,22 +7358,24 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
}
case llvm::Triple::NaCl:
return new NaClTargetInfo<X86_64TargetInfo>(Triple);
+ case llvm::Triple::PS4:
+ return new PS4OSTargetInfo<X86_64TargetInfo>(Triple);
default:
return new X86_64TargetInfo(Triple);
}
- case llvm::Triple::spir: {
- if (Triple.getOS() != llvm::Triple::UnknownOS ||
- Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
- return nullptr;
- return new SPIR32TargetInfo(Triple);
- }
- case llvm::Triple::spir64: {
- if (Triple.getOS() != llvm::Triple::UnknownOS ||
- Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
- return nullptr;
- return new SPIR64TargetInfo(Triple);
- }
+ case llvm::Triple::spir: {
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
+ return nullptr;
+ return new SPIR32TargetInfo(Triple);
+ }
+ case llvm::Triple::spir64: {
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
+ return nullptr;
+ return new SPIR64TargetInfo(Triple);
+ }
}
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
index ae9eb1a..6accb04 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_361/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp
index aa43ae2..9c73fd9 100644
--- a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp
@@ -32,6 +32,8 @@ raw_ostream& clang::operator<<(raw_ostream &Out,
Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
if (Optional<unsigned> Subminor = V.getSubminor())
Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
+ if (Optional<unsigned> Build = V.getBuild())
+ Out << (V.usesUnderscores() ? '_' : '.') << *Build;
return Out;
}
@@ -55,7 +57,7 @@ static bool parseInt(StringRef &input, unsigned &value) {
}
bool VersionTuple::tryParse(StringRef input) {
- unsigned major = 0, minor = 0, micro = 0;
+ unsigned major = 0, minor = 0, micro = 0, build = 0;
// Parse the major version, [0-9]+
if (parseInt(input, major)) return true;
@@ -80,9 +82,19 @@ bool VersionTuple::tryParse(StringRef input) {
input = input.substr(1);
if (parseInt(input, micro)) return true;
+ if (input.empty()) {
+ *this = VersionTuple(major, minor, micro);
+ return false;
+ }
+
+ // If we're not done, parse the micro version, \.[0-9]+
+ if (input[0] != '.') return true;
+ input = input.substr(1);
+ if (parseInt(input, build)) return true;
+
// If we have characters left over, it's an error.
if (!input.empty()) return true;
- *this = VersionTuple(major, minor, micro);
+ *this = VersionTuple(major, minor, micro, build);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
index c89195e..a36102c 100644
--- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -92,7 +92,7 @@ class RealFile : public File {
}
public:
- ~RealFile();
+ ~RealFile() override;
ErrorOr<Status> status() override;
ErrorOr<std::unique_ptr<MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize = -1,
@@ -324,20 +324,6 @@ directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
// VFSFromYAML implementation
//===-----------------------------------------------------------------------===/
-// Allow DenseMap<StringRef, ...>. This is useful below because we know all the
-// strings are literals and will outlive the map, and there is no reason to
-// store them.
-namespace llvm {
- template<>
- struct DenseMapInfo<StringRef> {
- // This assumes that "" will never be a valid key.
- static inline StringRef getEmptyKey() { return StringRef(""); }
- static inline StringRef getTombstoneKey() { return StringRef(); }
- static unsigned getHashValue(StringRef Val) { return HashString(Val); }
- static bool isEqual(StringRef LHS, StringRef RHS) { return LHS == RHS; }
- };
-}
-
namespace {
enum EntryKind {
@@ -362,7 +348,7 @@ class DirectoryEntry : public Entry {
Status S;
public:
- virtual ~DirectoryEntry();
+ ~DirectoryEntry() override;
DirectoryEntry(StringRef Name, std::vector<Entry *> Contents, Status S)
: Entry(EK_Directory, Name), Contents(std::move(Contents)),
S(std::move(S)) {}
@@ -498,7 +484,7 @@ private:
ErrorOr<Status> status(const Twine &Path, Entry *E);
public:
- ~VFSFromYAML();
+ ~VFSFromYAML() override;
/// \brief Parses \p Buffer, which is expected to be in YAML format and
/// returns a virtual file system representing its contents.
@@ -1134,7 +1120,7 @@ VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(const Twine &_Path,
if (Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
- llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
if (S)
CurrentEntry = *S;
else
@@ -1147,7 +1133,7 @@ std::error_code VFSFromYamlDirIterImpl::increment() {
if (++Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
- llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
if (!S)
return S.getError();
CurrentEntry = *S;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
index 7e7f7fa..cc8652e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
@@ -87,6 +87,8 @@ namespace clang {
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
uint64_t Members) const;
+ virtual bool shouldSignExtUnsignedType(QualType Ty) const;
+
bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t &Members) const;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
index 25ecec5..afcb9e5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
@@ -15,22 +15,22 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -55,44 +55,48 @@ class EmitAssemblyHelper {
Timer CodeGenerationTime;
- mutable PassManager *CodeGenPasses;
- mutable PassManager *PerModulePasses;
- mutable FunctionPassManager *PerFunctionPasses;
+ mutable legacy::PassManager *CodeGenPasses;
+ mutable legacy::PassManager *PerModulePasses;
+ mutable legacy::FunctionPassManager *PerFunctionPasses;
private:
- PassManager *getCodeGenPasses() const {
+ TargetIRAnalysis getTargetIRAnalysis() const {
+ if (TM)
+ return TM->getTargetIRAnalysis();
+
+ return TargetIRAnalysis();
+ }
+
+ legacy::PassManager *getCodeGenPasses() const {
if (!CodeGenPasses) {
- CodeGenPasses = new PassManager();
- CodeGenPasses->add(new DataLayoutPass());
- if (TM)
- TM->addAnalysisPasses(*CodeGenPasses);
+ CodeGenPasses = new legacy::PassManager();
+ CodeGenPasses->add(
+ createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
}
return CodeGenPasses;
}
- PassManager *getPerModulePasses() const {
+ legacy::PassManager *getPerModulePasses() const {
if (!PerModulePasses) {
- PerModulePasses = new PassManager();
- PerModulePasses->add(new DataLayoutPass());
- if (TM)
- TM->addAnalysisPasses(*PerModulePasses);
+ PerModulePasses = new legacy::PassManager();
+ PerModulePasses->add(
+ createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
}
return PerModulePasses;
}
- FunctionPassManager *getPerFunctionPasses() const {
+ legacy::FunctionPassManager *getPerFunctionPasses() const {
if (!PerFunctionPasses) {
- PerFunctionPasses = new FunctionPassManager(TheModule);
- PerFunctionPasses->add(new DataLayoutPass());
- if (TM)
- TM->addAnalysisPasses(*PerFunctionPasses);
+ PerFunctionPasses = new legacy::FunctionPassManager(TheModule);
+ PerFunctionPasses->add(
+ createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
}
return PerFunctionPasses;
}
void CreatePasses();
- /// CreateTargetMachine - Generates the TargetMachine.
+ /// Generates the TargetMachine.
/// Returns Null if it is unable to create the target machine.
/// Some of our clang tests specify triples which are not built
/// into clang. This is okay because these tests check the generated
@@ -102,10 +106,10 @@ private:
/// the requested target.
TargetMachine *CreateTargetMachine(bool MustCreateTM);
- /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
+ /// Add passes necessary to emit assembly or LLVM IR.
///
/// \return True on success.
- bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS);
+ bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS);
public:
EmitAssemblyHelper(DiagnosticsEngine &_Diags,
@@ -128,7 +132,7 @@ public:
std::unique_ptr<TargetMachine> TM;
- void EmitAssembly(BackendAction Action, raw_ostream *OS);
+ void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS);
};
// We need this wrapper to access LangOpts and CGOpts from extension functions
@@ -163,7 +167,7 @@ static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase
}
static void addSampleProfileLoaderPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper &>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
@@ -171,31 +175,44 @@ static void addSampleProfileLoaderPass(const PassManagerBuilder &Builder,
}
static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
PM.add(createAddDiscriminatorsPass());
}
static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
PM.add(createBoundsCheckingPass());
}
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- PM.add(createSanitizerCoverageModulePass(CGOpts.SanitizeCoverage));
+ SanitizerCoverageOptions Opts;
+ Opts.CoverageType =
+ static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType);
+ Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls;
+ Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB;
+ Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp;
+ Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;
+ PM.add(createSanitizerCoverageModulePass(Opts));
}
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
- PM.add(createAddressSanitizerFunctionPass());
- PM.add(createAddressSanitizerModulePass());
+ legacy::PassManagerBase &PM) {
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false));
+}
+
+static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true));
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
@@ -215,28 +232,36 @@ static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
}
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
PM.add(createThreadSanitizerPass());
}
static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
- PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFile));
+ PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles));
}
-static TargetLibraryInfo *createTLI(llvm::Triple &TargetTriple,
- const CodeGenOptions &CodeGenOpts) {
- TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
+static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
+ const CodeGenOptions &CodeGenOpts) {
+ TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
if (!CodeGenOpts.SimplifyLibCalls)
- TLI->disableAllFunctions();
- return TLI;
+ TLII->disableAllFunctions();
+
+ switch (CodeGenOpts.getVecLib()) {
+ case CodeGenOptions::Accelerate:
+ TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate);
+ break;
+ default:
+ break;
+ }
+ return TLII;
}
static void addSymbolRewriterPass(const CodeGenOptions &Opts,
- PassManager *MPM) {
+ legacy::PassManager *MPM) {
llvm::SymbolRewriter::RewriteDescriptorList DL;
llvm::SymbolRewriter::RewriteMapParser MapParser;
@@ -264,10 +289,10 @@ void EmitAssemblyHelper::CreatePasses() {
PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;
- PMBuilder.DisableTailCalls = CodeGenOpts.DisableTailCalls;
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,
@@ -294,7 +319,9 @@ void EmitAssemblyHelper::CreatePasses() {
addBoundsCheckingPass);
}
- if (CodeGenOpts.SanitizeCoverage) {
+ if (CodeGenOpts.SanitizeCoverageType ||
+ CodeGenOpts.SanitizeCoverageIndirectCalls ||
+ CodeGenOpts.SanitizeCoverageTraceCmp) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addSanitizerCoveragePass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
@@ -308,6 +335,13 @@ void EmitAssemblyHelper::CreatePasses() {
addAddressSanitizerPasses);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KernelAddress)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addKernelAddressSanitizerPasses);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addKernelAddressSanitizerPasses);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addMemorySanitizerPass);
@@ -331,7 +365,7 @@ void EmitAssemblyHelper::CreatePasses() {
// Figure out TargetLibraryInfo.
Triple TargetTriple(TheModule->getTargetTriple());
- PMBuilder.LibraryInfo = createTLI(TargetTriple, CodeGenOpts);
+ PMBuilder.LibraryInfo = createTLII(TargetTriple, CodeGenOpts);
switch (Inlining) {
case CodeGenOptions::NoInlining: break;
@@ -351,17 +385,15 @@ void EmitAssemblyHelper::CreatePasses() {
}
// Set up the per-function pass manager.
- FunctionPassManager *FPM = getPerFunctionPasses();
+ legacy::FunctionPassManager *FPM = getPerFunctionPasses();
if (CodeGenOpts.VerifyModule)
FPM->add(createVerifierPass());
PMBuilder.populateFunctionPassManager(*FPM);
// Set up the per-module pass manager.
- PassManager *MPM = getPerModulePasses();
+ legacy::PassManager *MPM = getPerModulePasses();
if (!CodeGenOpts.RewriteMapFiles.empty())
addSymbolRewriterPass(CodeGenOpts, MPM);
- if (CodeGenOpts.VerifyModule)
- MPM->add(createDebugInfoVerifierPass());
if (!CodeGenOpts.DisableGCov &&
(CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) {
@@ -375,6 +407,7 @@ void EmitAssemblyHelper::CreatePasses() {
Options.NoRedZone = CodeGenOpts.DisableRedZone;
Options.FunctionNamesInData =
!CodeGenOpts.CoverageNoFunctionNamesInData;
+ Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody;
MPM->add(createGCOVProfilerPass(Options));
if (CodeGenOpts.getDebugInfo() == CodeGenOptions::NoDebugInfo)
MPM->add(createStripSymbolsPass(true));
@@ -383,6 +416,7 @@ void EmitAssemblyHelper::CreatePasses() {
if (CodeGenOpts.ProfileInstrGenerate) {
InstrProfOptions Options;
Options.NoRedZone = CodeGenOpts.DisableRedZone;
+ Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
MPM->add(createInstrProfilingPass(Options));
}
@@ -421,23 +455,17 @@ 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());
- if (CodeGenOpts.NoGlobalMerge)
- BackendArgs.push_back("-enable-global-merge=false");
BackendArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
std::string FeaturesStr;
- if (TargetOpts.Features.size()) {
+ if (!TargetOpts.Features.empty()) {
SubtargetFeatures Features;
- for (std::vector<std::string>::const_iterator
- it = TargetOpts.Features.begin(),
- ie = TargetOpts.Features.end(); it != ie; ++it)
- Features.AddFeature(*it);
+ for (const std::string &Feature : TargetOpts.Features)
+ Features.AddFeature(Feature);
FeaturesStr = Features.getString();
}
@@ -461,6 +489,9 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
llvm::TargetOptions Options;
+ if (!TargetOpts.Reciprocals.empty())
+ Options.Reciprocals = TargetRecip(TargetOpts.Reciprocals);
+
Options.ThreadModel =
llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel)
.Case("posix", llvm::ThreadModel::POSIX)
@@ -472,15 +503,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
if (CodeGenOpts.CompressDebugSections)
Options.CompressDebugSections = true;
- // Set frame pointer elimination mode.
- if (!CodeGenOpts.DisableFPElim) {
- Options.NoFramePointerElim = false;
- } else if (CodeGenOpts.OmitLeafFramePointer) {
- Options.NoFramePointerElim = false;
- } else {
- Options.NoFramePointerElim = true;
- }
-
if (CodeGenOpts.UseInitArray)
Options.UseInitArray = true;
@@ -512,13 +534,11 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
- Options.UseSoftFloat = CodeGenOpts.SoftFloat;
Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
- Options.DisableTailCalls = CodeGenOpts.DisableTailCalls;
- Options.TrapFuncName = CodeGenOpts.TrapFuncName;
Options.PositionIndependentExecutable = LangOpts.PIELevel != 0;
Options.FunctionSections = CodeGenOpts.FunctionSections;
Options.DataSections = CodeGenOpts.DataSections;
+ Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
@@ -536,17 +556,16 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
}
bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
- formatted_raw_ostream &OS) {
+ raw_pwrite_stream &OS) {
// Create the code generator passes.
- PassManager *PM = getCodeGenPasses();
+ legacy::PassManager *PM = getCodeGenPasses();
// Add LibraryInfo.
llvm::Triple TargetTriple(TheModule->getTargetTriple());
- PM->add(createTLI(TargetTriple, CodeGenOpts));
-
- // Add Target specific analysis passes.
- TM->addAnalysisPasses(*PM);
+ std::unique_ptr<TargetLibraryInfoImpl> TLII(
+ createTLII(TargetTriple, CodeGenOpts));
+ PM->add(new TargetLibraryInfoWrapperPass(*TLII));
// Normal mode, emit a .s or .o file by running the code generator. Note,
// this also adds codegenerator level optimization passes.
@@ -561,8 +580,7 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
// Add ObjC ARC final-cleanup optimizations. This is done as part of the
// "codegen" passes so that it isn't run multiple times when there is
// inlining happening.
- if (LangOpts.ObjCAutoRefCount &&
- CodeGenOpts.OptimizationLevel > 0)
+ if (CodeGenOpts.OptimizationLevel > 0)
PM->add(createObjCARCContractPass());
if (TM->addPassesToEmitFile(*PM, OS, CGFT,
@@ -574,9 +592,9 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
return true;
}
-void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
+void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
+ raw_pwrite_stream *OS) {
TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
- llvm::formatted_raw_ostream FormattedOS;
bool UsesCodeGen = (Action != Backend_EmitNothing &&
Action != Backend_EmitBC &&
@@ -584,7 +602,10 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
if (!TM)
TM.reset(CreateTargetMachine(UsesCodeGen));
- if (UsesCodeGen && !TM) return;
+ if (UsesCodeGen && !TM)
+ return;
+ if (TM)
+ TheModule->setDataLayout(*TM->getDataLayout());
CreatePasses();
switch (Action) {
@@ -592,17 +613,17 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
break;
case Backend_EmitBC:
- getPerModulePasses()->add(createBitcodeWriterPass(*OS));
+ getPerModulePasses()->add(
+ createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists));
break;
case Backend_EmitLL:
- FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
- getPerModulePasses()->add(createPrintModulePass(FormattedOS));
+ getPerModulePasses()->add(
+ createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
break;
default:
- FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
- if (!AddEmitPasses(Action, FormattedOS))
+ if (!AddEmitPasses(Action, *OS))
return;
}
@@ -616,10 +637,9 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
PrettyStackTraceString CrashInfo("Per-function optimization");
PerFunctionPasses->doInitialization();
- for (Module::iterator I = TheModule->begin(),
- E = TheModule->end(); I != E; ++I)
- if (!I->isDeclaration())
- PerFunctionPasses->run(*I);
+ for (Function &F : *TheModule)
+ if (!F.isDeclaration())
+ PerFunctionPasses->run(F);
PerFunctionPasses->doFinalization();
}
@@ -639,7 +659,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
const clang::TargetOptions &TOpts,
const LangOptions &LOpts, StringRef TDesc,
Module *M, BackendAction Action,
- raw_ostream *OS) {
+ raw_pwrite_stream *OS) {
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
AsmHelper.EmitAssembly(Action, OS);
@@ -647,9 +667,8 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
// If an optional clang TargetInfo description string was passed in, use it to
// verify the LLVM TargetMachine's DataLayout.
if (AsmHelper.TM && !TDesc.empty()) {
- std::string DLDesc = AsmHelper.TM->getSubtargetImpl()
- ->getDataLayout()
- ->getStringRepresentation();
+ std::string DLDesc =
+ AsmHelper.TM->getDataLayout()->getStringRepresentation();
if (DLDesc != TDesc) {
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "backend data layout '%0' does not match "
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
index daac174..9839617 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
@@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CGCall.h"
+#include "CGRecordLayout.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -36,34 +37,95 @@ namespace {
CharUnits LValueAlign;
TypeEvaluationKind EvaluationKind;
bool UseLibcall;
+ LValue LVal;
+ CGBitFieldInfo BFI;
public:
- AtomicInfo(CodeGenFunction &CGF, LValue &lvalue) : CGF(CGF) {
- assert(lvalue.isSimple());
-
- AtomicTy = lvalue.getType();
- ValueTy = AtomicTy->castAs<AtomicType>()->getValueType();
- EvaluationKind = CGF.getEvaluationKind(ValueTy);
-
+ AtomicInfo(CodeGenFunction &CGF, LValue &lvalue)
+ : CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0),
+ EvaluationKind(TEK_Scalar), UseLibcall(true) {
+ assert(!lvalue.isGlobalReg());
ASTContext &C = CGF.getContext();
-
- uint64_t ValueAlignInBits;
- uint64_t AtomicAlignInBits;
- TypeInfo ValueTI = C.getTypeInfo(ValueTy);
- ValueSizeInBits = ValueTI.Width;
- ValueAlignInBits = ValueTI.Align;
-
- TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);
- AtomicSizeInBits = AtomicTI.Width;
- AtomicAlignInBits = AtomicTI.Align;
-
- assert(ValueSizeInBits <= AtomicSizeInBits);
- assert(ValueAlignInBits <= AtomicAlignInBits);
-
- AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);
- ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);
- if (lvalue.getAlignment().isZero())
- lvalue.setAlignment(AtomicAlign);
-
+ if (lvalue.isSimple()) {
+ AtomicTy = lvalue.getType();
+ if (auto *ATy = AtomicTy->getAs<AtomicType>())
+ ValueTy = ATy->getValueType();
+ else
+ ValueTy = AtomicTy;
+ EvaluationKind = CGF.getEvaluationKind(ValueTy);
+
+ uint64_t ValueAlignInBits;
+ uint64_t AtomicAlignInBits;
+ TypeInfo ValueTI = C.getTypeInfo(ValueTy);
+ ValueSizeInBits = ValueTI.Width;
+ ValueAlignInBits = ValueTI.Align;
+
+ TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);
+ AtomicSizeInBits = AtomicTI.Width;
+ AtomicAlignInBits = AtomicTI.Align;
+
+ assert(ValueSizeInBits <= AtomicSizeInBits);
+ assert(ValueAlignInBits <= AtomicAlignInBits);
+
+ AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);
+ ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);
+ if (lvalue.getAlignment().isZero())
+ lvalue.setAlignment(AtomicAlign);
+
+ LVal = lvalue;
+ } else if (lvalue.isBitField()) {
+ ValueTy = lvalue.getType();
+ ValueSizeInBits = C.getTypeSize(ValueTy);
+ auto &OrigBFI = lvalue.getBitFieldInfo();
+ auto Offset = OrigBFI.Offset % C.toBits(lvalue.getAlignment());
+ AtomicSizeInBits = C.toBits(
+ C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)
+ .RoundUpToAlignment(lvalue.getAlignment()));
+ auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldAddr());
+ auto OffsetInChars =
+ (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
+ lvalue.getAlignment();
+ VoidPtrAddr = CGF.Builder.CreateConstGEP1_64(
+ VoidPtrAddr, OffsetInChars.getQuantity());
+ auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ VoidPtrAddr,
+ CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(),
+ "atomic_bitfield_base");
+ BFI = OrigBFI;
+ BFI.Offset = Offset;
+ BFI.StorageSize = AtomicSizeInBits;
+ BFI.StorageOffset += OffsetInChars;
+ LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(),
+ lvalue.getAlignment());
+ LVal.setTBAAInfo(lvalue.getTBAAInfo());
+ AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
+ if (AtomicTy.isNull()) {
+ llvm::APInt Size(
+ /*numBits=*/32,
+ C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity());
+ AtomicTy = C.getConstantArrayType(C.CharTy, Size, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ }
+ AtomicAlign = ValueAlign = lvalue.getAlignment();
+ } else if (lvalue.isVectorElt()) {
+ ValueTy = lvalue.getType()->getAs<VectorType>()->getElementType();
+ ValueSizeInBits = C.getTypeSize(ValueTy);
+ AtomicTy = lvalue.getType();
+ AtomicSizeInBits = C.getTypeSize(AtomicTy);
+ AtomicAlign = ValueAlign = lvalue.getAlignment();
+ LVal = lvalue;
+ } else {
+ assert(lvalue.isExtVectorElt());
+ ValueTy = lvalue.getType();
+ ValueSizeInBits = C.getTypeSize(ValueTy);
+ AtomicTy = ValueTy = CGF.getContext().getExtVectorType(
+ lvalue.getType(), lvalue.getExtVectorAddr()
+ ->getType()
+ ->getPointerElementType()
+ ->getVectorNumElements());
+ AtomicSizeInBits = C.getTypeSize(AtomicTy);
+ AtomicAlign = ValueAlign = lvalue.getAlignment();
+ LVal = lvalue;
+ }
UseLibcall = !C.getTargetInfo().hasBuiltinAtomic(
AtomicSizeInBits, C.toBits(lvalue.getAlignment()));
}
@@ -76,6 +138,17 @@ namespace {
uint64_t getValueSizeInBits() const { return ValueSizeInBits; }
TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; }
bool shouldUseLibcall() const { return UseLibcall; }
+ const LValue &getAtomicLValue() const { return LVal; }
+ llvm::Value *getAtomicAddress() const {
+ if (LVal.isSimple())
+ return LVal.getAddress();
+ else if (LVal.isBitField())
+ return LVal.getBitFieldAddr();
+ else if (LVal.isVectorElt())
+ return LVal.getVectorAddr();
+ assert(LVal.isExtVectorElt());
+ return LVal.getExtVectorAddr();
+ }
/// Is the atomic size larger than the underlying value type?
///
@@ -87,7 +160,7 @@ namespace {
return (ValueSizeInBits != AtomicSizeInBits);
}
- bool emitMemSetZeroIfNecessary(LValue dest) const;
+ bool emitMemSetZeroIfNecessary() const;
llvm::Value *getAtomicSizeValue() const {
CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits);
@@ -99,37 +172,141 @@ namespace {
llvm::Value *emitCastToAtomicIntPointer(llvm::Value *addr) const;
/// Turn an atomic-layout object into an r-value.
- RValue convertTempToRValue(llvm::Value *addr,
- AggValueSlot resultSlot,
- SourceLocation loc) const;
+ RValue convertTempToRValue(llvm::Value *addr, AggValueSlot resultSlot,
+ SourceLocation loc, bool AsValue) const;
/// \brief Converts a rvalue to integer value.
llvm::Value *convertRValueToInt(RValue RVal) const;
- RValue convertIntToValue(llvm::Value *IntVal, AggValueSlot ResultSlot,
- SourceLocation Loc) const;
+ RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal,
+ AggValueSlot ResultSlot,
+ SourceLocation Loc, bool AsValue) const;
/// Copy an atomic r-value into atomic-layout memory.
- void emitCopyIntoMemory(RValue rvalue, LValue lvalue) const;
+ void emitCopyIntoMemory(RValue rvalue) const;
/// Project an l-value down to the value field.
- LValue projectValue(LValue lvalue) const {
- llvm::Value *addr = lvalue.getAddress();
+ LValue projectValue() const {
+ assert(LVal.isSimple());
+ llvm::Value *addr = getAtomicAddress();
if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(addr, 0);
+ addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
- return LValue::MakeAddr(addr, getValueType(), lvalue.getAlignment(),
- CGF.getContext(), lvalue.getTBAAInfo());
+ return LValue::MakeAddr(addr, getValueType(), LVal.getAlignment(),
+ CGF.getContext(), LVal.getTBAAInfo());
}
+ /// \brief Emits atomic load.
+ /// \returns Loaded value.
+ RValue EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
+ bool AsValue, llvm::AtomicOrdering AO,
+ bool IsVolatile);
+
+ /// \brief Emits atomic compare-and-exchange sequence.
+ /// \param Expected Expected value.
+ /// \param Desired Desired value.
+ /// \param Success Atomic ordering for success operation.
+ /// \param Failure Atomic ordering for failed operation.
+ /// \param IsWeak true if atomic operation is weak, false otherwise.
+ /// \returns Pair of values: previous value from storage (value type) and
+ /// boolean flag (i1 type) with true if success and false otherwise.
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchange(
+ RValue Expected, RValue Desired,
+ llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
+ llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
+ bool IsWeak = false);
+
+ /// \brief Emits atomic update.
+ /// \param AO Atomic ordering.
+ /// \param UpdateOp Update operation for the current lvalue.
+ void EmitAtomicUpdate(llvm::AtomicOrdering AO,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile);
+ /// \brief Emits atomic update.
+ /// \param AO Atomic ordering.
+ void EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,
+ bool IsVolatile);
+
/// Materialize an atomic r-value in atomic-layout memory.
llvm::Value *materializeRValue(RValue rvalue) const;
+ /// \brief Translates LLVM atomic ordering to GNU atomic ordering for
+ /// libcalls.
+ static AtomicExpr::AtomicOrderingKind
+ translateAtomicOrdering(const llvm::AtomicOrdering AO);
+
private:
bool requiresMemSetZero(llvm::Type *type) const;
+
+ /// \brief Creates temp alloca for intermediate operations on atomic value.
+ llvm::Value *CreateTempAlloca() const;
+
+ /// \brief Emits atomic load as a libcall.
+ void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
+ llvm::AtomicOrdering AO, bool IsVolatile);
+ /// \brief Emits atomic load as LLVM instruction.
+ llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
+ /// \brief Emits atomic compare-and-exchange op as a libcall.
+ llvm::Value *EmitAtomicCompareExchangeLibcall(
+ llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
+ llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
+ llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent);
+ /// \brief Emits atomic compare-and-exchange op as LLVM instruction.
+ std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(
+ llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
+ llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
+ llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
+ bool IsWeak = false);
+ /// \brief Emit atomic update as libcalls.
+ void
+ EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile);
+ /// \brief Emit atomic update as LLVM instructions.
+ void EmitAtomicUpdateOp(llvm::AtomicOrdering AO,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile);
+ /// \brief Emit atomic update as libcalls.
+ void EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, RValue UpdateRVal,
+ bool IsVolatile);
+ /// \brief Emit atomic update as LLVM instructions.
+ void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRal,
+ bool IsVolatile);
};
}
+AtomicExpr::AtomicOrderingKind
+AtomicInfo::translateAtomicOrdering(const llvm::AtomicOrdering AO) {
+ switch (AO) {
+ case llvm::Unordered:
+ case llvm::NotAtomic:
+ case llvm::Monotonic:
+ return AtomicExpr::AO_ABI_memory_order_relaxed;
+ case llvm::Acquire:
+ return AtomicExpr::AO_ABI_memory_order_acquire;
+ case llvm::Release:
+ return AtomicExpr::AO_ABI_memory_order_release;
+ case llvm::AcquireRelease:
+ return AtomicExpr::AO_ABI_memory_order_acq_rel;
+ case llvm::SequentiallyConsistent:
+ return AtomicExpr::AO_ABI_memory_order_seq_cst;
+ }
+ llvm_unreachable("Unhandled AtomicOrdering");
+}
+
+llvm::Value *AtomicInfo::CreateTempAlloca() const {
+ auto *TempAlloca = CGF.CreateMemTemp(
+ (LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy
+ : AtomicTy,
+ "atomic-temp");
+ TempAlloca->setAlignment(getAtomicAlignment().getQuantity());
+ // Cast to pointer to value type for bitfields.
+ if (LVal.isBitField())
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ TempAlloca, getAtomicAddress()->getType());
+ return TempAlloca;
+}
+
static RValue emitAtomicLibcall(CodeGenFunction &CGF,
StringRef fnName,
QualType resultType,
@@ -172,14 +349,16 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
llvm_unreachable("bad evaluation kind");
}
-bool AtomicInfo::emitMemSetZeroIfNecessary(LValue dest) const {
- llvm::Value *addr = dest.getAddress();
+bool AtomicInfo::emitMemSetZeroIfNecessary() const {
+ assert(LVal.isSimple());
+ llvm::Value *addr = LVal.getAddress();
if (!requiresMemSetZero(addr->getType()->getPointerElementType()))
return false;
- CGF.Builder.CreateMemSet(addr, llvm::ConstantInt::get(CGF.Int8Ty, 0),
- AtomicSizeInBits / 8,
- dest.getAlignment().getQuantity());
+ CGF.Builder.CreateMemSet(
+ addr, llvm::ConstantInt::get(CGF.Int8Ty, 0),
+ CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(),
+ LVal.getAlignment().getQuantity());
return true;
}
@@ -901,29 +1080,53 @@ llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
RValue AtomicInfo::convertTempToRValue(llvm::Value *addr,
AggValueSlot resultSlot,
- SourceLocation loc) const {
- if (EvaluationKind == TEK_Aggregate)
- return resultSlot.asRValue();
-
- // Drill into the padding structure if we have one.
- if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(addr, 0);
-
- // Otherwise, just convert the temporary to an r-value using the
- // normal conversion routine.
- return CGF.convertTempToRValue(addr, getValueType(), loc);
+ SourceLocation loc, bool AsValue) const {
+ if (LVal.isSimple()) {
+ if (EvaluationKind == TEK_Aggregate)
+ return resultSlot.asRValue();
+
+ // Drill into the padding structure if we have one.
+ if (hasPadding())
+ addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
+
+ // Otherwise, just convert the temporary to an r-value using the
+ // normal conversion routine.
+ return CGF.convertTempToRValue(addr, getValueType(), loc);
+ }
+ if (!AsValue)
+ // Get RValue from temp memory as atomic for non-simple lvalues
+ return RValue::get(
+ CGF.Builder.CreateAlignedLoad(addr, AtomicAlign.getQuantity()));
+ if (LVal.isBitField())
+ return CGF.EmitLoadOfBitfieldLValue(LValue::MakeBitfield(
+ addr, LVal.getBitFieldInfo(), LVal.getType(), LVal.getAlignment()));
+ if (LVal.isVectorElt())
+ return CGF.EmitLoadOfLValue(LValue::MakeVectorElt(addr, LVal.getVectorIdx(),
+ LVal.getType(),
+ LVal.getAlignment()),
+ loc);
+ assert(LVal.isExtVectorElt());
+ return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
+ addr, LVal.getExtVectorElts(), LVal.getType(), LVal.getAlignment()));
}
-RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
- AggValueSlot ResultSlot,
- SourceLocation Loc) const {
+RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
+ AggValueSlot ResultSlot,
+ SourceLocation Loc,
+ bool AsValue) const {
// Try not to in some easy cases.
assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
- if (getEvaluationKind() == TEK_Scalar && !hasPadding()) {
- auto *ValTy = CGF.ConvertTypeForMem(ValueTy);
+ if (getEvaluationKind() == TEK_Scalar &&
+ (((!LVal.isBitField() ||
+ LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
+ !hasPadding()) ||
+ !AsValue)) {
+ auto *ValTy = AsValue
+ ? CGF.ConvertTypeForMem(ValueTy)
+ : getAtomicAddress()->getType()->getPointerElementType();
if (ValTy->isIntegerTy()) {
assert(IntVal->getType() == ValTy && "Different integer types.");
- return RValue::get(IntVal);
+ return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
} else if (ValTy->isPointerTy())
return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
@@ -935,13 +1138,13 @@ RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
llvm::Value *Temp;
bool TempIsVolatile = false;
CharUnits TempAlignment;
- if (getEvaluationKind() == TEK_Aggregate) {
+ if (AsValue && getEvaluationKind() == TEK_Aggregate) {
assert(!ResultSlot.isIgnored());
Temp = ResultSlot.getAddr();
TempAlignment = getValueAlignment();
TempIsVolatile = ResultSlot.isVolatile();
} else {
- Temp = CGF.CreateMemTemp(getAtomicType(), "atomic-temp");
+ Temp = CreateTempAlloca();
TempAlignment = getAtomicAlignment();
}
@@ -950,93 +1153,146 @@ RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
CGF.Builder.CreateAlignedStore(IntVal, CastTemp, TempAlignment.getQuantity())
->setVolatile(TempIsVolatile);
- return convertTempToRValue(Temp, ResultSlot, Loc);
+ return convertTempToRValue(Temp, ResultSlot, Loc, AsValue);
}
-/// Emit a load from an l-value of atomic type. Note that the r-value
-/// we produce is an r-value of the atomic *value* type.
-RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
- AggValueSlot resultSlot) {
- AtomicInfo atomics(*this, src);
+void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
+ llvm::AtomicOrdering AO, bool) {
+ // void __atomic_load(size_t size, void *mem, void *return, int order);
+ CallArgList Args;
+ Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicAddress())),
+ CGF.getContext().VoidPtrTy);
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(AddForLoaded)),
+ CGF.getContext().VoidPtrTy);
+ Args.add(RValue::get(
+ llvm::ConstantInt::get(CGF.IntTy, translateAtomicOrdering(AO))),
+ CGF.getContext().IntTy);
+ emitAtomicLibcall(CGF, "__atomic_load", CGF.getContext().VoidTy, Args);
+}
- // Check whether we should use a library call.
- if (atomics.shouldUseLibcall()) {
- llvm::Value *tempAddr;
- if (!resultSlot.isIgnored()) {
- assert(atomics.getEvaluationKind() == TEK_Aggregate);
- tempAddr = resultSlot.getAddr();
- } else {
- tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
- }
+llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
+ bool IsVolatile) {
+ // Okay, we're doing this natively.
+ llvm::Value *Addr = emitCastToAtomicIntPointer(getAtomicAddress());
+ llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
+ Load->setAtomic(AO);
- // void __atomic_load(size_t size, void *mem, void *return, int order);
- CallArgList args;
- args.add(RValue::get(atomics.getAtomicSizeValue()),
- getContext().getSizeType());
- args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())),
- getContext().VoidPtrTy);
- args.add(RValue::get(EmitCastToVoidPtr(tempAddr)),
- getContext().VoidPtrTy);
- args.add(RValue::get(llvm::ConstantInt::get(
- IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),
- getContext().IntTy);
- emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args);
+ // Other decoration.
+ Load->setAlignment(getAtomicAlignment().getQuantity());
+ if (IsVolatile)
+ Load->setVolatile(true);
+ if (LVal.getTBAAInfo())
+ CGF.CGM.DecorateInstruction(Load, LVal.getTBAAInfo());
+ return Load;
+}
+
+/// An LValue is a candidate for having its loads and stores be made atomic if
+/// we are operating under /volatile:ms *and* the LValue itself is volatile and
+/// performing such an operation can be performed without a libcall.
+bool CodeGenFunction::LValueIsSuitableForInlineAtomic(LValue LV) {
+ AtomicInfo AI(*this, LV);
+ bool IsVolatile = LV.isVolatile() || hasVolatileMember(LV.getType());
+ // An atomic is inline if we don't need to use a libcall.
+ bool AtomicIsInline = !AI.shouldUseLibcall();
+ return CGM.getCodeGenOpts().MSVolatile && IsVolatile && AtomicIsInline;
+}
- // Produce the r-value.
- return atomics.convertTempToRValue(tempAddr, resultSlot, loc);
+/// An type is a candidate for having its loads and stores be made atomic if
+/// we are operating under /volatile:ms *and* we know the access is volatile and
+/// performing such an operation can be performed without a libcall.
+bool CodeGenFunction::typeIsSuitableForInlineAtomic(QualType Ty,
+ bool IsVolatile) const {
+ // An atomic is inline if we don't need to use a libcall (e.g. it is builtin).
+ bool AtomicIsInline = getContext().getTargetInfo().hasBuiltinAtomic(
+ getContext().getTypeSize(Ty), getContext().getTypeAlign(Ty));
+ return CGM.getCodeGenOpts().MSVolatile && IsVolatile && AtomicIsInline;
+}
+
+RValue CodeGenFunction::EmitAtomicLoad(LValue LV, SourceLocation SL,
+ AggValueSlot Slot) {
+ llvm::AtomicOrdering AO;
+ bool IsVolatile = LV.isVolatileQualified();
+ if (LV.getType()->isAtomicType()) {
+ AO = llvm::SequentiallyConsistent;
+ } else {
+ AO = llvm::Acquire;
+ IsVolatile = true;
}
+ return EmitAtomicLoad(LV, SL, AO, IsVolatile, Slot);
+}
- // Okay, we're doing this natively.
- llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress());
- llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load");
- load->setAtomic(llvm::SequentiallyConsistent);
+RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
+ bool AsValue, llvm::AtomicOrdering AO,
+ bool IsVolatile) {
+ // Check whether we should use a library call.
+ if (shouldUseLibcall()) {
+ llvm::Value *TempAddr;
+ if (LVal.isSimple() && !ResultSlot.isIgnored()) {
+ assert(getEvaluationKind() == TEK_Aggregate);
+ TempAddr = ResultSlot.getAddr();
+ } else
+ TempAddr = CreateTempAlloca();
+
+ EmitAtomicLoadLibcall(TempAddr, AO, IsVolatile);
+
+ // Okay, turn that back into the original value or whole atomic (for
+ // non-simple lvalues) type.
+ return convertTempToRValue(TempAddr, ResultSlot, Loc, AsValue);
+ }
- // Other decoration.
- load->setAlignment(src.getAlignment().getQuantity());
- if (src.isVolatileQualified())
- load->setVolatile(true);
- if (src.getTBAAInfo())
- CGM.DecorateInstruction(load, src.getTBAAInfo());
+ // Okay, we're doing this natively.
+ auto *Load = EmitAtomicLoadOp(AO, IsVolatile);
// If we're ignoring an aggregate return, don't do anything.
- if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored())
+ if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
return RValue::getAggregate(nullptr, false);
- // Okay, turn that back into the original value type.
- return atomics.convertIntToValue(load, resultSlot, loc);
+ // Okay, turn that back into the original value or atomic (for non-simple
+ // lvalues) type.
+ return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue);
}
-
+/// Emit a load from an l-value of atomic type. Note that the r-value
+/// we produce is an r-value of the atomic *value* type.
+RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
+ llvm::AtomicOrdering AO, bool IsVolatile,
+ AggValueSlot resultSlot) {
+ AtomicInfo Atomics(*this, src);
+ return Atomics.EmitAtomicLoad(resultSlot, loc, /*AsValue=*/true, AO,
+ IsVolatile);
+}
/// Copy an r-value into memory as part of storing to an atomic type.
/// This needs to create a bit-pattern suitable for atomic operations.
-void AtomicInfo::emitCopyIntoMemory(RValue rvalue, LValue dest) const {
+void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
+ assert(LVal.isSimple());
// If we have an r-value, the rvalue should be of the atomic type,
// which means that the caller is responsible for having zeroed
// any padding. Just do an aggregate copy of that type.
if (rvalue.isAggregate()) {
- CGF.EmitAggregateCopy(dest.getAddress(),
+ CGF.EmitAggregateCopy(getAtomicAddress(),
rvalue.getAggregateAddr(),
getAtomicType(),
(rvalue.isVolatileQualified()
- || dest.isVolatileQualified()),
- dest.getAlignment());
+ || LVal.isVolatileQualified()),
+ LVal.getAlignment());
return;
}
// Okay, otherwise we're copying stuff.
// Zero out the buffer if necessary.
- emitMemSetZeroIfNecessary(dest);
+ emitMemSetZeroIfNecessary();
// Drill past the padding if present.
- dest = projectValue(dest);
+ LValue TempLVal = projectValue();
// Okay, store the rvalue in.
if (rvalue.isScalar()) {
- CGF.EmitStoreOfScalar(rvalue.getScalarVal(), dest, /*init*/ true);
+ CGF.EmitStoreOfScalar(rvalue.getScalarVal(), TempLVal, /*init*/ true);
} else {
- CGF.EmitStoreOfComplex(rvalue.getComplexVal(), dest, /*init*/ true);
+ CGF.EmitStoreOfComplex(rvalue.getComplexVal(), TempLVal, /*init*/ true);
}
}
@@ -1050,22 +1306,24 @@ llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const {
return rvalue.getAggregateAddr();
// Otherwise, make a temporary and materialize into it.
- llvm::Value *temp = CGF.CreateMemTemp(getAtomicType(), "atomic-store-temp");
- LValue tempLV = CGF.MakeAddrLValue(temp, getAtomicType(), getAtomicAlignment());
- emitCopyIntoMemory(rvalue, tempLV);
- return temp;
+ LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType(),
+ getAtomicAlignment());
+ AtomicInfo Atomics(CGF, TempLV);
+ Atomics.emitCopyIntoMemory(rvalue);
+ return TempLV.getAddress();
}
llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
// If we've got a scalar value of the right size, try to avoid going
// through memory.
- if (RVal.isScalar() && !hasPadding()) {
+ if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) {
llvm::Value *Value = RVal.getScalarVal();
if (isa<llvm::IntegerType>(Value->getType()))
- return Value;
+ return CGF.EmitToMemory(Value, ValueTy);
else {
- llvm::IntegerType *InputIntTy =
- llvm::IntegerType::get(CGF.getLLVMContext(), getValueSizeInBits());
+ llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
+ CGF.getLLVMContext(),
+ LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());
if (isa<llvm::PointerType>(Value->getType()))
return CGF.Builder.CreatePtrToInt(Value, InputIntTy);
else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))
@@ -1082,12 +1340,324 @@ llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
getAtomicAlignment().getQuantity());
}
+std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
+ llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
+ llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) {
+ // Do the atomic store.
+ auto *Addr = emitCastToAtomicIntPointer(getAtomicAddress());
+ auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
+ Success, Failure);
+ // Other decoration.
+ Inst->setVolatile(LVal.isVolatileQualified());
+ Inst->setWeak(IsWeak);
+
+ // Okay, turn that back into the original value type.
+ auto *PreviousVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/0);
+ auto *SuccessFailureVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/1);
+ return std::make_pair(PreviousVal, SuccessFailureVal);
+}
+
+llvm::Value *
+AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,
+ llvm::Value *DesiredAddr,
+ llvm::AtomicOrdering Success,
+ llvm::AtomicOrdering Failure) {
+ // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
+ // void *desired, int success, int failure);
+ CallArgList Args;
+ Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicAddress())),
+ CGF.getContext().VoidPtrTy);
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(ExpectedAddr)),
+ CGF.getContext().VoidPtrTy);
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(DesiredAddr)),
+ CGF.getContext().VoidPtrTy);
+ Args.add(RValue::get(llvm::ConstantInt::get(
+ CGF.IntTy, translateAtomicOrdering(Success))),
+ CGF.getContext().IntTy);
+ Args.add(RValue::get(llvm::ConstantInt::get(
+ CGF.IntTy, translateAtomicOrdering(Failure))),
+ CGF.getContext().IntTy);
+ auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange",
+ CGF.getContext().BoolTy, Args);
+
+ return SuccessFailureRVal.getScalarVal();
+}
+
+std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
+ RValue Expected, RValue Desired, llvm::AtomicOrdering Success,
+ llvm::AtomicOrdering Failure, bool IsWeak) {
+ if (Failure >= Success)
+ // Don't assert on undefined behavior.
+ Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success);
+
+ // Check whether we should use a library call.
+ if (shouldUseLibcall()) {
+ // Produce a source address.
+ auto *ExpectedAddr = materializeRValue(Expected);
+ auto *DesiredAddr = materializeRValue(Desired);
+ auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr,
+ Success, Failure);
+ return std::make_pair(
+ convertTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false),
+ Res);
+ }
+
+ // If we've got a scalar value of the right size, try to avoid going
+ // through memory.
+ auto *ExpectedVal = convertRValueToInt(Expected);
+ auto *DesiredVal = convertRValueToInt(Desired);
+ auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
+ Failure, IsWeak);
+ return std::make_pair(
+ ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false),
+ Res.second);
+}
+
+static void
+EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ llvm::Value *DesiredAddr) {
+ llvm::Value *Ptr = nullptr;
+ LValue UpdateLVal;
+ RValue UpRVal;
+ LValue AtomicLVal = Atomics.getAtomicLValue();
+ LValue DesiredLVal;
+ if (AtomicLVal.isSimple()) {
+ UpRVal = OldRVal;
+ DesiredLVal =
+ LValue::MakeAddr(DesiredAddr, AtomicLVal.getType(),
+ AtomicLVal.getAlignment(), CGF.CGM.getContext());
+ } else {
+ // Build new lvalue for temp address
+ Ptr = Atomics.materializeRValue(OldRVal);
+ if (AtomicLVal.isBitField()) {
+ UpdateLVal =
+ LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
+ AtomicLVal.getType(), AtomicLVal.getAlignment());
+ DesiredLVal =
+ LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
+ AtomicLVal.getType(), AtomicLVal.getAlignment());
+ } else if (AtomicLVal.isVectorElt()) {
+ UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ DesiredLVal = LValue::MakeVectorElt(
+ DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ } else {
+ assert(AtomicLVal.isExtVectorElt());
+ UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ DesiredLVal = LValue::MakeExtVectorElt(
+ DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ }
+ UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
+ DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
+ UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation());
+ }
+ // Store new value in the corresponding memory area
+ RValue NewRVal = UpdateOp(UpRVal);
+ if (NewRVal.isScalar()) {
+ CGF.EmitStoreThroughLValue(NewRVal, DesiredLVal);
+ } else {
+ assert(NewRVal.isComplex());
+ CGF.EmitStoreOfComplex(NewRVal.getComplexVal(), DesiredLVal,
+ /*isInit=*/false);
+ }
+}
+
+void AtomicInfo::EmitAtomicUpdateLibcall(
+ llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile) {
+ auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
+
+ llvm::Value *ExpectedAddr = CreateTempAlloca();
+
+ EmitAtomicLoadLibcall(ExpectedAddr, AO, IsVolatile);
+ auto *ContBB = CGF.createBasicBlock("atomic_cont");
+ auto *ExitBB = CGF.createBasicBlock("atomic_exit");
+ CGF.EmitBlock(ContBB);
+ auto *DesiredAddr = CreateTempAlloca();
+ if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
+ requiresMemSetZero(
+ getAtomicAddress()->getType()->getPointerElementType())) {
+ auto *OldVal = CGF.Builder.CreateAlignedLoad(
+ ExpectedAddr, getAtomicAlignment().getQuantity());
+ CGF.Builder.CreateAlignedStore(OldVal, DesiredAddr,
+ getAtomicAlignment().getQuantity());
+ }
+ auto OldRVal = convertTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false);
+ EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr);
+ auto *Res =
+ EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr, AO, Failure);
+ CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+}
+
+void AtomicInfo::EmitAtomicUpdateOp(
+ llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile) {
+ auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
+
+ // Do the atomic load.
+ auto *OldVal = EmitAtomicLoadOp(AO, IsVolatile);
+ // For non-simple lvalues perform compare-and-swap procedure.
+ auto *ContBB = CGF.createBasicBlock("atomic_cont");
+ auto *ExitBB = CGF.createBasicBlock("atomic_exit");
+ auto *CurBB = CGF.Builder.GetInsertBlock();
+ CGF.EmitBlock(ContBB);
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
+ /*NumReservedValues=*/2);
+ PHI->addIncoming(OldVal, CurBB);
+ auto *NewAtomicAddr = CreateTempAlloca();
+ auto *NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
+ if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
+ requiresMemSetZero(
+ getAtomicAddress()->getType()->getPointerElementType())) {
+ CGF.Builder.CreateAlignedStore(PHI, NewAtomicIntAddr,
+ getAtomicAlignment().getQuantity());
+ }
+ auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false);
+ EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
+ auto *DesiredVal = CGF.Builder.CreateAlignedLoad(
+ NewAtomicIntAddr, getAtomicAlignment().getQuantity());
+ // Try to write new value using cmpxchg operation
+ auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
+ PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
+ CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+}
+
+static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,
+ RValue UpdateRVal, llvm::Value *DesiredAddr) {
+ LValue AtomicLVal = Atomics.getAtomicLValue();
+ LValue DesiredLVal;
+ // Build new lvalue for temp address
+ if (AtomicLVal.isBitField()) {
+ DesiredLVal =
+ LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
+ AtomicLVal.getType(), AtomicLVal.getAlignment());
+ } else if (AtomicLVal.isVectorElt()) {
+ DesiredLVal =
+ LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),
+ AtomicLVal.getType(), AtomicLVal.getAlignment());
+ } else {
+ assert(AtomicLVal.isExtVectorElt());
+ DesiredLVal = LValue::MakeExtVectorElt(
+ DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
+ AtomicLVal.getAlignment());
+ }
+ DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
+ // Store new value in the corresponding memory area
+ assert(UpdateRVal.isScalar());
+ CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal);
+}
+
+void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
+ RValue UpdateRVal, bool IsVolatile) {
+ auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
+
+ llvm::Value *ExpectedAddr = CreateTempAlloca();
+
+ EmitAtomicLoadLibcall(ExpectedAddr, AO, IsVolatile);
+ auto *ContBB = CGF.createBasicBlock("atomic_cont");
+ auto *ExitBB = CGF.createBasicBlock("atomic_exit");
+ CGF.EmitBlock(ContBB);
+ auto *DesiredAddr = CreateTempAlloca();
+ if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
+ requiresMemSetZero(
+ getAtomicAddress()->getType()->getPointerElementType())) {
+ auto *OldVal = CGF.Builder.CreateAlignedLoad(
+ ExpectedAddr, getAtomicAlignment().getQuantity());
+ CGF.Builder.CreateAlignedStore(OldVal, DesiredAddr,
+ getAtomicAlignment().getQuantity());
+ }
+ EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr);
+ auto *Res =
+ EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr, AO, Failure);
+ CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+}
+
+void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,
+ bool IsVolatile) {
+ auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
+
+ // Do the atomic load.
+ auto *OldVal = EmitAtomicLoadOp(AO, IsVolatile);
+ // For non-simple lvalues perform compare-and-swap procedure.
+ auto *ContBB = CGF.createBasicBlock("atomic_cont");
+ auto *ExitBB = CGF.createBasicBlock("atomic_exit");
+ auto *CurBB = CGF.Builder.GetInsertBlock();
+ CGF.EmitBlock(ContBB);
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
+ /*NumReservedValues=*/2);
+ PHI->addIncoming(OldVal, CurBB);
+ auto *NewAtomicAddr = CreateTempAlloca();
+ auto *NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
+ if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
+ requiresMemSetZero(
+ getAtomicAddress()->getType()->getPointerElementType())) {
+ CGF.Builder.CreateAlignedStore(PHI, NewAtomicIntAddr,
+ getAtomicAlignment().getQuantity());
+ }
+ EmitAtomicUpdateValue(CGF, *this, UpdateRVal, NewAtomicAddr);
+ auto *DesiredVal = CGF.Builder.CreateAlignedLoad(
+ NewAtomicIntAddr, getAtomicAlignment().getQuantity());
+ // Try to write new value using cmpxchg operation
+ auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
+ PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
+ CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+}
+
+void AtomicInfo::EmitAtomicUpdate(
+ llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile) {
+ if (shouldUseLibcall()) {
+ EmitAtomicUpdateLibcall(AO, UpdateOp, IsVolatile);
+ } else {
+ EmitAtomicUpdateOp(AO, UpdateOp, IsVolatile);
+ }
+}
+
+void AtomicInfo::EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,
+ bool IsVolatile) {
+ if (shouldUseLibcall()) {
+ EmitAtomicUpdateLibcall(AO, UpdateRVal, IsVolatile);
+ } else {
+ EmitAtomicUpdateOp(AO, UpdateRVal, IsVolatile);
+ }
+}
+
+void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue lvalue,
+ bool isInit) {
+ bool IsVolatile = lvalue.isVolatileQualified();
+ llvm::AtomicOrdering AO;
+ if (lvalue.getType()->isAtomicType()) {
+ AO = llvm::SequentiallyConsistent;
+ } else {
+ AO = llvm::Release;
+ IsVolatile = true;
+ }
+ return EmitAtomicStore(rvalue, lvalue, AO, IsVolatile, isInit);
+}
+
/// Emit a store to an l-value of atomic type.
///
/// Note that the r-value is expected to be an r-value *of the atomic
/// type*; this means that for aggregate r-values, it should include
/// storage for any padding that was necessary.
-void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {
+void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
+ llvm::AtomicOrdering AO, bool IsVolatile,
+ bool isInit) {
// If this is an aggregate r-value, it should agree in type except
// maybe for address-space qualification.
assert(!rvalue.isAggregate() ||
@@ -1095,54 +1665,64 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {
== dest.getAddress()->getType()->getPointerElementType());
AtomicInfo atomics(*this, dest);
+ LValue LVal = atomics.getAtomicLValue();
// If this is an initialization, just put the value there normally.
- if (isInit) {
- atomics.emitCopyIntoMemory(rvalue, dest);
- return;
- }
+ if (LVal.isSimple()) {
+ if (isInit) {
+ atomics.emitCopyIntoMemory(rvalue);
+ return;
+ }
- // Check whether we should use a library call.
- if (atomics.shouldUseLibcall()) {
- // Produce a source address.
- llvm::Value *srcAddr = atomics.materializeRValue(rvalue);
+ // Check whether we should use a library call.
+ if (atomics.shouldUseLibcall()) {
+ // Produce a source address.
+ llvm::Value *srcAddr = atomics.materializeRValue(rvalue);
- // void __atomic_store(size_t size, void *mem, void *val, int order)
- CallArgList args;
- args.add(RValue::get(atomics.getAtomicSizeValue()),
- getContext().getSizeType());
- args.add(RValue::get(EmitCastToVoidPtr(dest.getAddress())),
- getContext().VoidPtrTy);
- args.add(RValue::get(EmitCastToVoidPtr(srcAddr)),
- getContext().VoidPtrTy);
- args.add(RValue::get(llvm::ConstantInt::get(
- IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),
- getContext().IntTy);
- emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args);
+ // void __atomic_store(size_t size, void *mem, void *val, int order)
+ CallArgList args;
+ args.add(RValue::get(atomics.getAtomicSizeValue()),
+ getContext().getSizeType());
+ args.add(RValue::get(EmitCastToVoidPtr(atomics.getAtomicAddress())),
+ getContext().VoidPtrTy);
+ args.add(RValue::get(EmitCastToVoidPtr(srcAddr)), getContext().VoidPtrTy);
+ args.add(RValue::get(llvm::ConstantInt::get(
+ IntTy, AtomicInfo::translateAtomicOrdering(AO))),
+ getContext().IntTy);
+ emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args);
+ return;
+ }
+
+ // Okay, we're doing this natively.
+ llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
+
+ // Do the atomic store.
+ llvm::Value *addr =
+ atomics.emitCastToAtomicIntPointer(atomics.getAtomicAddress());
+ intValue = Builder.CreateIntCast(
+ intValue, addr->getType()->getPointerElementType(), /*isSigned=*/false);
+ llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
+
+ // Initializations don't need to be atomic.
+ if (!isInit)
+ store->setAtomic(AO);
+
+ // Other decoration.
+ store->setAlignment(dest.getAlignment().getQuantity());
+ if (IsVolatile)
+ store->setVolatile(true);
+ if (dest.getTBAAInfo())
+ CGM.DecorateInstruction(store, dest.getTBAAInfo());
return;
}
- // Okay, we're doing this natively.
- llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
-
- // Do the atomic store.
- llvm::Value *addr = atomics.emitCastToAtomicIntPointer(dest.getAddress());
- llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
-
- // Initializations don't need to be atomic.
- if (!isInit) store->setAtomic(llvm::SequentiallyConsistent);
-
- // Other decoration.
- store->setAlignment(dest.getAlignment().getQuantity());
- if (dest.isVolatileQualified())
- store->setVolatile(true);
- if (dest.getTBAAInfo())
- CGM.DecorateInstruction(store, dest.getTBAAInfo());
+ // Emit simple atomic update operation.
+ atomics.EmitAtomicUpdate(AO, rvalue, IsVolatile);
}
/// Emit a compare-and-exchange op for atomic type.
///
-std::pair<RValue, RValue> CodeGenFunction::EmitAtomicCompareExchange(
+std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(
LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,
llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak,
AggValueSlot Slot) {
@@ -1156,56 +1736,15 @@ std::pair<RValue, RValue> CodeGenFunction::EmitAtomicCompareExchange(
Obj.getAddress()->getType()->getPointerElementType());
AtomicInfo Atomics(*this, Obj);
- if (Failure >= Success)
- // Don't assert on undefined behavior.
- Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success);
-
- auto Alignment = Atomics.getValueAlignment();
- // Check whether we should use a library call.
- if (Atomics.shouldUseLibcall()) {
- auto *ExpectedAddr = Atomics.materializeRValue(Expected);
- // Produce a source address.
- auto *DesiredAddr = Atomics.materializeRValue(Desired);
- // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
- // void *desired, int success, int failure);
- CallArgList Args;
- Args.add(RValue::get(Atomics.getAtomicSizeValue()),
- getContext().getSizeType());
- Args.add(RValue::get(EmitCastToVoidPtr(Obj.getAddress())),
- getContext().VoidPtrTy);
- Args.add(RValue::get(EmitCastToVoidPtr(ExpectedAddr)),
- getContext().VoidPtrTy);
- Args.add(RValue::get(EmitCastToVoidPtr(DesiredAddr)),
- getContext().VoidPtrTy);
- Args.add(RValue::get(llvm::ConstantInt::get(IntTy, Success)),
- getContext().IntTy);
- Args.add(RValue::get(llvm::ConstantInt::get(IntTy, Failure)),
- getContext().IntTy);
- auto SuccessFailureRVal = emitAtomicLibcall(
- *this, "__atomic_compare_exchange", getContext().BoolTy, Args);
- auto *PreviousVal =
- Builder.CreateAlignedLoad(ExpectedAddr, Alignment.getQuantity());
- return std::make_pair(RValue::get(PreviousVal), SuccessFailureRVal);
- }
-
- // If we've got a scalar value of the right size, try to avoid going
- // through memory.
- auto *ExpectedIntVal = Atomics.convertRValueToInt(Expected);
- auto *DesiredIntVal = Atomics.convertRValueToInt(Desired);
-
- // Do the atomic store.
- auto *Addr = Atomics.emitCastToAtomicIntPointer(Obj.getAddress());
- auto *Inst = Builder.CreateAtomicCmpXchg(Addr, ExpectedIntVal, DesiredIntVal,
- Success, Failure);
- // Other decoration.
- Inst->setVolatile(Obj.isVolatileQualified());
- Inst->setWeak(IsWeak);
+ return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure,
+ IsWeak);
+}
- // Okay, turn that back into the original value type.
- auto *PreviousVal = Builder.CreateExtractValue(Inst, /*Idxs=*/0);
- auto *SuccessFailureVal = Builder.CreateExtractValue(Inst, /*Idxs=*/1);
- return std::make_pair(Atomics.convertIntToValue(PreviousVal, Slot, Loc),
- RValue::get(SuccessFailureVal));
+void CodeGenFunction::EmitAtomicUpdate(
+ LValue LVal, llvm::AtomicOrdering AO,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp, bool IsVolatile) {
+ AtomicInfo Atomics(*this, LVal);
+ Atomics.EmitAtomicUpdate(AO, UpdateOp, IsVolatile);
}
void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
@@ -1214,13 +1753,13 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
switch (atomics.getEvaluationKind()) {
case TEK_Scalar: {
llvm::Value *value = EmitScalarExpr(init);
- atomics.emitCopyIntoMemory(RValue::get(value), dest);
+ atomics.emitCopyIntoMemory(RValue::get(value));
return;
}
case TEK_Complex: {
ComplexPairTy value = EmitComplexExpr(init);
- atomics.emitCopyIntoMemory(RValue::getComplex(value), dest);
+ atomics.emitCopyIntoMemory(RValue::getComplex(value));
return;
}
@@ -1229,8 +1768,8 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
// of atomic type.
bool Zeroed = false;
if (!init->getType()->isAtomicType()) {
- Zeroed = atomics.emitMemSetZeroIfNecessary(dest);
- dest = atomics.projectValue(dest);
+ Zeroed = atomics.emitMemSetZeroIfNecessary();
+ dest = atomics.projectValue();
}
// Evaluate the expression directly into the destination.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index b98460a..3fd344c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -621,8 +621,8 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
}
// GEP down to the address.
- llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address,
- capture.getIndex());
+ llvm::Value *addr = CGF.Builder.CreateStructGEP(
+ blockInfo.StructureType, blockInfo.Address, capture.getIndex());
// We can use that GEP as the dominating IP.
if (!blockInfo.DominatingIP)
@@ -721,6 +721,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Build the block descriptor.
llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
+ llvm::Type *blockTy = blockInfo.StructureType;
llvm::AllocaInst *blockAddr = blockInfo.Address;
assert(blockAddr && "block has no address!");
@@ -732,14 +733,17 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
// Initialize the block literal.
- Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
- Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
- Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0),
- Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
- Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
- "block.invoke"));
- Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4,
+ Builder.CreateStore(
+ isa, Builder.CreateStructGEP(blockTy, blockAddr, 0, "block.isa"));
+ Builder.CreateStore(
+ llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ Builder.CreateStructGEP(blockTy, blockAddr, 1, "block.flags"));
+ Builder.CreateStore(
+ llvm::ConstantInt::get(IntTy, 0),
+ Builder.CreateStructGEP(blockTy, blockAddr, 2, "block.reserved"));
+ Builder.CreateStore(
+ blockFn, Builder.CreateStructGEP(blockTy, blockAddr, 3, "block.invoke"));
+ Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockTy, blockAddr, 4,
"block.descriptor"));
// Finally, capture all the values into the block.
@@ -747,9 +751,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// First, 'this'.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr = Builder.CreateStructGEP(blockAddr,
- blockInfo.CXXThisIndex,
- "block.captured-this.addr");
+ llvm::Value *addr = Builder.CreateStructGEP(
+ blockTy, blockAddr, blockInfo.CXXThisIndex, "block.captured-this.addr");
Builder.CreateStore(LoadCXXThis(), addr);
}
@@ -766,9 +769,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// This will be a [[type]]*, except that a byref entry will just be
// an i8**.
- llvm::Value *blockField =
- Builder.CreateStructGEP(blockAddr, capture.getIndex(),
- "block.captured");
+ llvm::Value *blockField = Builder.CreateStructGEP(
+ blockTy, blockAddr, capture.getIndex(), "block.captured");
// Compute the address of the thing we're going to move into the
// block literal.
@@ -779,7 +781,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
BlockInfo->getCapture(variable);
// This is a [[type]]*, except that a byref entry wil just be an i8**.
- src = Builder.CreateStructGEP(LoadBlockStruct(),
+ src = Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
enclosingCapture.getIndex(),
"block.capture.addr");
} else if (blockDecl->isConversionFromLambda()) {
@@ -964,7 +966,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal.
- llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3);
+ llvm::Value *FuncPtr = Builder.CreateStructGEP(
+ CGM.getGenericBlockLiteralType(), BlockLiteral, 3);
BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy);
@@ -1004,26 +1007,27 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
if (capture.isConstant()) return LocalDeclMap[variable];
llvm::Value *addr =
- Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
- "block.capture.addr");
+ Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
+ capture.getIndex(), "block.capture.addr");
if (isByRef) {
// addr should be a void** right now. Load, then cast the result
// to byref*.
addr = Builder.CreateLoad(addr);
- llvm::PointerType *byrefPointerType
- = llvm::PointerType::get(BuildByRefType(variable), 0);
+ auto *byrefType = BuildByRefType(variable);
+ llvm::PointerType *byrefPointerType = llvm::PointerType::get(byrefType, 0);
addr = Builder.CreateBitCast(addr, byrefPointerType,
"byref.addr");
// Follow the forwarding pointer.
- addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding");
+ addr = Builder.CreateStructGEP(byrefType, addr, 1, "byref.forwarding");
addr = Builder.CreateLoad(addr, "byref.addr.forwarded");
// Cast back to byref* and GEP over to the actual object.
addr = Builder.CreateBitCast(addr, byrefPointerType);
- addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable),
+ addr = Builder.CreateStructGEP(byrefType, addr,
+ getByRefValueLLVMField(variable).second,
variable->getNameAsString());
}
@@ -1136,8 +1140,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
args.push_back(&selfDecl);
// Now add the rest of the parameters.
- for (auto i : blockDecl->params())
- args.push_back(i);
+ args.append(blockDecl->param_begin(), blockDecl->param_end());
// Create the function declaration.
const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
@@ -1178,7 +1181,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
Alloca->setAlignment(Align);
// Set the DebugLocation to empty, so the store is recognized as a
// frame setup instruction by llvm::DwarfDebug::beginFunction().
- ApplyDebugLocation NL(*this);
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
BlockPointerDbgLoc = Alloca;
}
@@ -1186,9 +1189,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
// If we have a C++ 'this' reference, go ahead and force it into
// existence now.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr = Builder.CreateStructGEP(BlockPointer,
- blockInfo.CXXThisIndex,
- "block.captured-this");
+ llvm::Value *addr =
+ Builder.CreateStructGEP(blockInfo.StructureType, BlockPointer,
+ blockInfo.CXXThisIndex, "block.captured-this");
CXXThisValue = Builder.CreateLoad(addr, "this");
}
@@ -1218,8 +1221,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
EmitLambdaBlockInvokeBody();
else {
PGO.assignRegionCounters(blockDecl, fn);
- RegionCounter Cnt = getPGORegionCounter(blockDecl->getBody());
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(blockDecl->getBody());
EmitStmt(blockDecl->getBody());
}
@@ -1328,11 +1330,10 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
nullptr, SC_Static,
false,
false);
- // Create a scope with an artificial location for the body of this function.
- ApplyDebugLocation NL(*this);
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- ArtificialLocation AL(*this);
-
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
llvm::Value *src = GetAddrOfLocalVar(&srcDecl);
@@ -1404,8 +1405,10 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
}
unsigned index = capture.getIndex();
- llvm::Value *srcField = Builder.CreateStructGEP(src, index);
- llvm::Value *dstField = Builder.CreateStructGEP(dst, index);
+ llvm::Value *srcField =
+ Builder.CreateStructGEP(blockInfo.StructureType, src, index);
+ llvm::Value *dstField =
+ Builder.CreateStructGEP(blockInfo.StructureType, dst, index);
// If there's an explicit copy expression, we do that.
if (copyExpr) {
@@ -1500,9 +1503,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
nullptr, SC_Static,
false, false);
// Create a scope with an artificial location for the body of this function.
- ApplyDebugLocation NL(*this);
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- ArtificialLocation AL(*this);
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1562,7 +1565,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
}
unsigned index = capture.getIndex();
- llvm::Value *srcField = Builder.CreateStructGEP(src, index);
+ llvm::Value *srcField =
+ Builder.CreateStructGEP(blockInfo.StructureType, src, index);
// If there's an explicit copy expression, we do that.
if (dtor) {
@@ -1801,13 +1805,15 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst);
destField = CGF.Builder.CreateLoad(destField);
destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
- destField = CGF.Builder.CreateStructGEP(destField, valueFieldIndex, "x");
+ destField = CGF.Builder.CreateStructGEP(&byrefType, destField,
+ valueFieldIndex, "x");
// src->x
llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src);
srcField = CGF.Builder.CreateLoad(srcField);
srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
- srcField = CGF.Builder.CreateStructGEP(srcField, valueFieldIndex, "x");
+ srcField =
+ CGF.Builder.CreateStructGEP(&byrefType, srcField, valueFieldIndex, "x");
byrefInfo.emitCopy(CGF, destField, srcField);
}
@@ -1868,7 +1874,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
llvm::Value *V = CGF.GetAddrOfLocalVar(&src);
V = CGF.Builder.CreateLoad(V);
V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0));
- V = CGF.Builder.CreateStructGEP(V, byrefValueIndex, "x");
+ V = CGF.Builder.CreateStructGEP(&byrefType, V, byrefValueIndex, "x");
byrefInfo.emitDispose(CGF, V);
}
@@ -1925,7 +1931,7 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
const VarDecl &var = *emission.Variable;
QualType type = var.getType();
- unsigned byrefValueIndex = getByRefValueLLVMField(&var);
+ unsigned byrefValueIndex = getByRefValueLLVMField(&var).second;
if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
@@ -1995,18 +2001,20 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
}
-unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
+std::pair<llvm::Type *, unsigned>
+CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
assert(ByRefValueInfo.count(VD) && "Did not find value!");
-
- return ByRefValueInfo.find(VD)->second.second;
+
+ return ByRefValueInfo.find(VD)->second;
}
llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
const VarDecl *V) {
- llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
+ auto P = getByRefValueLLVMField(V);
+ llvm::Value *Loc =
+ Builder.CreateStructGEP(P.first, BaseAddr, 1, "forwarding");
Loc = Builder.CreateLoad(Loc);
- Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
- V->getNameAsString());
+ Loc = Builder.CreateStructGEP(P.first, Loc, P.second, V->getNameAsString());
return Loc;
}
@@ -2143,11 +2151,12 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
if (type.isObjCGCWeak())
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
+ Builder.CreateStore(V,
+ Builder.CreateStructGEP(nullptr, addr, 0, "byref.isa"));
// Store the address of the variable into its own forwarding pointer.
- Builder.CreateStore(addr,
- Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
+ Builder.CreateStore(
+ addr, Builder.CreateStructGEP(nullptr, addr, 1, "byref.forwarding"));
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -2193,25 +2202,26 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
printf("\n");
}
}
-
+
Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(addr, 2, "byref.flags"));
+ Builder.CreateStructGEP(nullptr, addr, 2, "byref.flags"));
CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
- Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
+ Builder.CreateStore(V,
+ Builder.CreateStructGEP(nullptr, addr, 3, "byref.size"));
if (helpers) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+ llvm::Value *copy_helper = Builder.CreateStructGEP(nullptr, addr, 4);
Builder.CreateStore(helpers->CopyHelper, copy_helper);
- llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(nullptr, addr, 5);
Builder.CreateStore(helpers->DisposeHelper, destroy_helper);
}
if (ByRefHasLifetime && HasByrefExtendedLayout) {
llvm::Constant* ByrefLayoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
- llvm::Value *ByrefInfoAddr = Builder.CreateStructGEP(addr, helpers ? 6 : 4,
- "byref.layout");
+ llvm::Value *ByrefInfoAddr =
+ Builder.CreateStructGEP(nullptr, addr, helpers ? 6 : 4, "byref.layout");
// cast destination to pointer to source type.
llvm::Type *DesTy = ByrefLayoutInfo->getType();
DesTy = DesTy->getPointerTo();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
index 72ba4fa..6610659 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
@@ -33,7 +33,7 @@ protected:
llvm::BasicBlock *BB,
llvm::BasicBlock::iterator InsertPt) const;
private:
- void operator=(const CGBuilderInserter &) LLVM_DELETED_FUNCTION;
+ void operator=(const CGBuilderInserter &) = delete;
CodeGenFunction *CGF;
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
index 635e342..9e53870 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
@@ -21,9 +22,11 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
+#include <sstream>
using namespace clang;
using namespace CodeGen;
@@ -79,9 +82,9 @@ static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V,
/// Utility to insert an atomic instruction based on Instrinsic::ID
/// and the expression node.
-static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
- llvm::AtomicRMWInst::BinOp Kind,
- const CallExpr *E) {
+static Value *MakeBinaryAtomicValue(CodeGenFunction &CGF,
+ llvm::AtomicRMWInst::BinOp Kind,
+ const CallExpr *E) {
QualType T = E->getType();
assert(E->getArg(0)->getType()->isPointerType());
assert(CGF.getContext().hasSameUnqualifiedType(T,
@@ -105,8 +108,13 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
llvm::Value *Result =
CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1],
llvm::SequentiallyConsistent);
- Result = EmitFromInt(CGF, Result, T, ValueType);
- return RValue::get(Result);
+ return EmitFromInt(CGF, Result, T, ValueType);
+}
+
+static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
+ llvm::AtomicRMWInst::BinOp Kind,
+ const CallExpr *E) {
+ return RValue::get(MakeBinaryAtomicValue(CGF, Kind, E));
}
/// Utility to insert an atomic instruction based Instrinsic::ID and
@@ -148,6 +156,47 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
return RValue::get(Result);
}
+/// @brief Utility to insert an atomic cmpxchg instruction.
+///
+/// @param CGF The current codegen function.
+/// @param E Builtin call expression to convert to cmpxchg.
+/// arg0 - address to operate on
+/// arg1 - value to compare with
+/// arg2 - new value
+/// @param ReturnBool Specifies whether to return success flag of
+/// cmpxchg result or the old value.
+///
+/// @returns result of cmpxchg, according to ReturnBool
+static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E,
+ bool ReturnBool) {
+ QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType();
+ llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0));
+ unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace();
+
+ llvm::IntegerType *IntType = llvm::IntegerType::get(
+ CGF.getLLVMContext(), CGF.getContext().getTypeSize(T));
+ llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
+
+ Value *Args[3];
+ Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType);
+ Args[1] = CGF.EmitScalarExpr(E->getArg(1));
+ llvm::Type *ValueType = Args[1]->getType();
+ Args[1] = EmitToInt(CGF, Args[1], T, IntType);
+ Args[2] = EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)), T, IntType);
+
+ Value *Pair = CGF.Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
+ llvm::SequentiallyConsistent,
+ llvm::SequentiallyConsistent);
+ if (ReturnBool)
+ // Extract boolean success flag and zext it to int.
+ return CGF.Builder.CreateZExt(CGF.Builder.CreateExtractValue(Pair, 1),
+ CGF.ConvertType(E->getType()));
+ else
+ // Extract old value and emit it using the same type as compare value.
+ return EmitFromInt(CGF, CGF.Builder.CreateExtractValue(Pair, 0), T,
+ ValueType);
+}
+
/// EmitFAbs - Emit a call to @llvm.fabs().
static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
Value *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType());
@@ -156,6 +205,27 @@ static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
return Call;
}
+/// Emit the computation of the sign bit for a floating point value. Returns
+/// the i1 sign bit value.
+static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
+ LLVMContext &C = CGF.CGM.getLLVMContext();
+
+ llvm::Type *Ty = V->getType();
+ int Width = Ty->getPrimitiveSizeInBits();
+ llvm::Type *IntTy = llvm::IntegerType::get(C, Width);
+ V = CGF.Builder.CreateBitCast(V, IntTy);
+ if (Ty->isPPC_FP128Ty()) {
+ // The higher-order double comes first, and so we need to truncate the
+ // pair to extract the overall sign. The order of the pair is the same
+ // in both little- and big-Endian modes.
+ Width >>= 1;
+ IntTy = llvm::IntegerType::get(C, Width);
+ V = CGF.Builder.CreateTrunc(V, IntTy);
+ }
+ Value *Zero = llvm::Constant::getNullValue(IntTy);
+ return CGF.Builder.CreateICmpSLT(V, Zero);
+}
+
static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn,
const CallExpr *E, llvm::Value *calleeValue) {
return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E,
@@ -181,7 +251,7 @@ static llvm::Value *EmitOverflowIntrinsic(CodeGenFunction &CGF,
"arguments have the same integer width?)");
llvm::Value *Callee = CGF.CGM.getIntrinsic(IntrinsicID, X->getType());
- llvm::Value *Tmp = CGF.Builder.CreateCall2(Callee, X, Y);
+ llvm::Value *Tmp = CGF.Builder.CreateCall(Callee, {X, Y});
Carry = CGF.Builder.CreateExtractValue(Tmp, 1);
return CGF.Builder.CreateExtractValue(Tmp, 0);
}
@@ -230,8 +300,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
DstPtr = Builder.CreateBitCast(DstPtr, Type);
SrcPtr = Builder.CreateBitCast(SrcPtr, Type);
- return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy),
- DstPtr, SrcPtr));
+ return RValue::get(Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy),
+ {DstPtr, SrcPtr}));
}
case Builtin::BI__builtin_abs:
case Builtin::BI__builtin_labs:
@@ -309,7 +379,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ResultType = ConvertType(E->getType());
Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef());
- Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef);
+ Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef});
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
"cast");
@@ -326,7 +396,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ResultType = ConvertType(E->getType());
Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef());
- Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef);
+ Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef});
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
"cast");
@@ -342,9 +412,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
llvm::Type *ResultType = ConvertType(E->getType());
- Value *Tmp = Builder.CreateAdd(Builder.CreateCall2(F, ArgValue,
- Builder.getTrue()),
- llvm::ConstantInt::get(ArgType, 1));
+ Value *Tmp =
+ Builder.CreateAdd(Builder.CreateCall(F, {ArgValue, Builder.getTrue()}),
+ llvm::ConstantInt::get(ArgType, 1));
Value *Zero = llvm::Constant::getNullValue(ArgType);
Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero");
Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs");
@@ -389,11 +459,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *ArgValue = EmitScalarExpr(E->getArg(0));
llvm::Type *ArgType = ArgValue->getType();
- Value *FnExpect = CGM.getIntrinsic(Intrinsic::expect, ArgType);
Value *ExpectedValue = EmitScalarExpr(E->getArg(1));
+ // Don't generate llvm.expect on -O0 as the backend won't use it for
+ // anything.
+ // Note, we still IRGen ExpectedValue because it could have side-effects.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return RValue::get(ArgValue);
- Value *Result = Builder.CreateCall2(FnExpect, ArgValue, ExpectedValue,
- "expval");
+ Value *FnExpect = CGM.getIntrinsic(Intrinsic::expect, ArgType);
+ Value *Result =
+ Builder.CreateCall(FnExpect, {ArgValue, ExpectedValue}, "expval");
return RValue::get(Result);
}
case Builtin::BI__builtin_assume_aligned: {
@@ -444,7 +519,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// FIXME: Get right address space.
llvm::Type *Tys[] = { ResType, Builder.getInt8PtrTy(0) };
Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys);
- return RValue::get(Builder.CreateCall2(F, EmitScalarExpr(E->getArg(0)),CI));
+ return RValue::get(
+ Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0)), CI}));
}
case Builtin::BI__builtin_prefetch: {
Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
@@ -455,7 +531,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::ConstantInt::get(Int32Ty, 3);
Value *Data = llvm::ConstantInt::get(Int32Ty, 1);
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
- return RValue::get(Builder.CreateCall4(F, Address, RW, Locality, Data));
+ return RValue::get(Builder.CreateCall(F, {Address, RW, Locality, Data}));
}
case Builtin::BI__builtin_readcyclecounter: {
Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter);
@@ -465,16 +541,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Begin = EmitScalarExpr(E->getArg(0));
Value *End = EmitScalarExpr(E->getArg(1));
Value *F = CGM.getIntrinsic(Intrinsic::clear_cache);
- return RValue::get(Builder.CreateCall2(F, Begin, End));
- }
- case Builtin::BI__builtin_trap: {
- Value *F = CGM.getIntrinsic(Intrinsic::trap);
- return RValue::get(Builder.CreateCall(F));
- }
- case Builtin::BI__debugbreak: {
- Value *F = CGM.getIntrinsic(Intrinsic::debugtrap);
- return RValue::get(Builder.CreateCall(F));
+ return RValue::get(Builder.CreateCall(F, {Begin, End}));
}
+ case Builtin::BI__builtin_trap:
+ return RValue::get(EmitTrapCall(Intrinsic::trap));
+ case Builtin::BI__debugbreak:
+ return RValue::get(EmitTrapCall(Intrinsic::debugtrap));
case Builtin::BI__builtin_unreachable: {
if (SanOpts.has(SanitizerKind::Unreachable)) {
SanitizerScope SanScope(this);
@@ -498,7 +570,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Exponent = EmitScalarExpr(E->getArg(1));
llvm::Type *ArgType = Base->getType();
Value *F = CGM.getIntrinsic(Intrinsic::powi, ArgType);
- return RValue::get(Builder.CreateCall2(F, Base, Exponent));
+ return RValue::get(Builder.CreateCall(F, {Base, Exponent}));
}
case Builtin::BI__builtin_isgreater:
@@ -551,8 +623,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
}
- // TODO: BI__builtin_isinf_sign
- // isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0
+ case Builtin::BI__builtin_isinf_sign: {
+ // isinf_sign(x) -> fabs(x) == infinity ? (signbit(x) ? -1 : 1) : 0
+ Value *Arg = EmitScalarExpr(E->getArg(0));
+ Value *AbsArg = EmitFAbs(*this, Arg);
+ Value *IsInf = Builder.CreateFCmpOEQ(
+ AbsArg, ConstantFP::getInfinity(Arg->getType()), "isinf");
+ Value *IsNeg = EmitSignBit(*this, Arg);
+
+ llvm::Type *IntTy = ConvertType(E->getType());
+ Value *Zero = Constant::getNullValue(IntTy);
+ Value *One = ConstantInt::get(IntTy, 1);
+ Value *NegativeOne = ConstantInt::get(IntTy, -1);
+ Value *SignResult = Builder.CreateSelect(IsNeg, NegativeOne, One);
+ Value *Result = Builder.CreateSelect(IsInf, SignResult, Zero);
+ return RValue::get(Result);
+ }
case Builtin::BI__builtin_isnormal: {
// isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min
@@ -654,6 +740,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
std::pair<llvm::Value*, unsigned> Dest =
EmitPointerWithAlignment(E->getArg(0));
Value *SizeVal = EmitScalarExpr(E->getArg(1));
+ EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ E->getArg(0)->getExprLoc(), FD, 0);
Builder.CreateMemSet(Dest.first, Builder.getInt8(0), SizeVal,
Dest.second, false);
return RValue::get(Dest.first);
@@ -666,6 +754,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = EmitScalarExpr(E->getArg(2));
unsigned Align = std::min(Dest.second, Src.second);
+ EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ E->getArg(0)->getExprLoc(), FD, 0);
+ EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(),
+ E->getArg(1)->getExprLoc(), FD, 1);
Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false);
return RValue::get(Dest.first);
}
@@ -723,6 +815,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = EmitScalarExpr(E->getArg(2));
unsigned Align = std::min(Dest.second, Src.second);
+ EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ E->getArg(0)->getExprLoc(), FD, 0);
+ EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(),
+ E->getArg(1)->getExprLoc(), FD, 1);
Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false);
return RValue::get(Dest.first);
}
@@ -733,6 +829,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
Builder.getInt8Ty());
Value *SizeVal = EmitScalarExpr(E->getArg(2));
+ EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ E->getArg(0)->getExprLoc(), FD, 0);
Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false);
return RValue::get(Dest.first);
}
@@ -815,7 +913,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *F = CGM.getIntrinsic(IntTy->getBitWidth() == 32
? Intrinsic::eh_return_i32
: Intrinsic::eh_return_i64);
- Builder.CreateCall2(F, Int, Ptr);
+ Builder.CreateCall(F, {Int, Ptr});
Builder.CreateUnreachable();
// We do need to preserve an insertion point.
@@ -864,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);
@@ -1001,58 +1099,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_val_compare_and_swap_2:
case Builtin::BI__sync_val_compare_and_swap_4:
case Builtin::BI__sync_val_compare_and_swap_8:
- case Builtin::BI__sync_val_compare_and_swap_16: {
- QualType T = E->getType();
- llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0));
- unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace();
-
- llvm::IntegerType *IntType =
- llvm::IntegerType::get(getLLVMContext(),
- getContext().getTypeSize(T));
- llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
-
- Value *Args[3];
- Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType);
- Args[1] = EmitScalarExpr(E->getArg(1));
- llvm::Type *ValueType = Args[1]->getType();
- Args[1] = EmitToInt(*this, Args[1], T, IntType);
- Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
-
- Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
- llvm::SequentiallyConsistent,
- llvm::SequentiallyConsistent);
- Result = Builder.CreateExtractValue(Result, 0);
- Result = EmitFromInt(*this, Result, T, ValueType);
- return RValue::get(Result);
- }
+ case Builtin::BI__sync_val_compare_and_swap_16:
+ return RValue::get(MakeAtomicCmpXchgValue(*this, E, false));
case Builtin::BI__sync_bool_compare_and_swap_1:
case Builtin::BI__sync_bool_compare_and_swap_2:
case Builtin::BI__sync_bool_compare_and_swap_4:
case Builtin::BI__sync_bool_compare_and_swap_8:
- case Builtin::BI__sync_bool_compare_and_swap_16: {
- QualType T = E->getArg(1)->getType();
- llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0));
- unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace();
-
- llvm::IntegerType *IntType =
- llvm::IntegerType::get(getLLVMContext(),
- getContext().getTypeSize(T));
- llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
-
- Value *Args[3];
- Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType);
- Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType);
- Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
-
- Value *Pair = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
- llvm::SequentiallyConsistent,
- llvm::SequentiallyConsistent);
- Value *Result = Builder.CreateExtractValue(Pair, 1);
- // zext bool to int.
- Result = Builder.CreateZExt(Result, ConvertType(E->getType()));
- return RValue::get(Result);
- }
+ case Builtin::BI__sync_bool_compare_and_swap_16:
+ return RValue::get(MakeAtomicCmpXchgValue(*this, E, true));
case Builtin::BI__sync_swap_1:
case Builtin::BI__sync_swap_2:
@@ -1357,6 +1412,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, Arg0));
}
+ case Builtin::BI__builtin_pow:
+ case Builtin::BI__builtin_powf:
+ case Builtin::BI__builtin_powl:
case Builtin::BIpow:
case Builtin::BIpowf:
case Builtin::BIpowl: {
@@ -1367,7 +1425,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Exponent = EmitScalarExpr(E->getArg(1));
llvm::Type *ArgType = Base->getType();
Value *F = CGM.getIntrinsic(Intrinsic::pow, ArgType);
- return RValue::get(Builder.CreateCall2(F, Base, Exponent));
+ return RValue::get(Builder.CreateCall(F, {Base, Exponent}));
}
case Builtin::BIfma:
@@ -1380,32 +1438,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *FirstArg = EmitScalarExpr(E->getArg(0));
llvm::Type *ArgType = FirstArg->getType();
Value *F = CGM.getIntrinsic(Intrinsic::fma, ArgType);
- return RValue::get(Builder.CreateCall3(F, FirstArg,
- EmitScalarExpr(E->getArg(1)),
- EmitScalarExpr(E->getArg(2))));
+ return RValue::get(
+ Builder.CreateCall(F, {FirstArg, EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2))}));
}
case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl: {
- LLVMContext &C = CGM.getLLVMContext();
-
- Value *Arg = EmitScalarExpr(E->getArg(0));
- llvm::Type *ArgTy = Arg->getType();
- int ArgWidth = ArgTy->getPrimitiveSizeInBits();
- llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth);
- Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy);
- if (ArgTy->isPPC_FP128Ty()) {
- // The higher-order double comes first, and so we need to truncate the
- // pair to extract the overall sign. The order of the pair is the same
- // in both little- and big-Endian modes.
- ArgWidth >>= 1;
- ArgIntTy = llvm::IntegerType::get(C, ArgWidth);
- BCArg = Builder.CreateTrunc(BCArg, ArgIntTy);
- }
- Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy);
- Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp);
- return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
+ return RValue::get(
+ Builder.CreateZExt(EmitSignBit(*this, EmitScalarExpr(E->getArg(0))),
+ ConvertType(E->getType())));
}
case Builtin::BI__builtin_annotation: {
llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0));
@@ -1650,6 +1693,76 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Builder.CreateAlignedLoad(IntToPtr, /*Align=*/4, /*isVolatile=*/true);
return RValue::get(Load);
}
+
+ case Builtin::BI__exception_code:
+ case Builtin::BI_exception_code:
+ return RValue::get(EmitSEHExceptionCode());
+ case Builtin::BI__exception_info:
+ case Builtin::BI_exception_info:
+ return RValue::get(EmitSEHExceptionInfo());
+ case Builtin::BI__abnormal_termination:
+ case Builtin::BI_abnormal_termination:
+ return RValue::get(EmitSEHAbnormalTermination());
+ case Builtin::BI_setjmpex: {
+ if (getTarget().getTriple().isOSMSVCRT()) {
+ llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy};
+ llvm::AttributeSet ReturnsTwiceAttr =
+ AttributeSet::get(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::ReturnsTwice);
+ llvm::Constant *SetJmpEx = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
+ "_setjmpex", ReturnsTwiceAttr);
+ llvm::Value *Buf = Builder.CreateBitOrPointerCast(
+ EmitScalarExpr(E->getArg(0)), Int8PtrTy);
+ llvm::Value *FrameAddr =
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
+ ConstantInt::get(Int32Ty, 0));
+ llvm::Value *Args[] = {Buf, FrameAddr};
+ llvm::CallSite CS = EmitRuntimeCallOrInvoke(SetJmpEx, Args);
+ CS.setAttributes(ReturnsTwiceAttr);
+ return RValue::get(CS.getInstruction());
+ }
+ break;
+ }
+ case Builtin::BI_setjmp: {
+ if (getTarget().getTriple().isOSMSVCRT()) {
+ llvm::AttributeSet ReturnsTwiceAttr =
+ AttributeSet::get(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::ReturnsTwice);
+ llvm::Value *Buf = Builder.CreateBitOrPointerCast(
+ EmitScalarExpr(E->getArg(0)), Int8PtrTy);
+ llvm::CallSite CS;
+ if (getTarget().getTriple().getArch() == llvm::Triple::x86) {
+ llvm::Type *ArgTypes[] = {Int8PtrTy, IntTy};
+ llvm::Constant *SetJmp3 = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/true),
+ "_setjmp3", ReturnsTwiceAttr);
+ llvm::Value *Count = ConstantInt::get(IntTy, 0);
+ llvm::Value *Args[] = {Buf, Count};
+ CS = EmitRuntimeCallOrInvoke(SetJmp3, Args);
+ } else {
+ llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy};
+ llvm::Constant *SetJmp = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
+ "_setjmp", ReturnsTwiceAttr);
+ llvm::Value *FrameAddr =
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
+ ConstantInt::get(Int32Ty, 0));
+ llvm::Value *Args[] = {Buf, FrameAddr};
+ CS = EmitRuntimeCallOrInvoke(SetJmp, Args);
+ }
+ CS.setAttributes(ReturnsTwiceAttr);
+ return RValue::get(CS.getInstruction());
+ }
+ break;
+ }
+
+ case Builtin::BI__GetExceptionInfo: {
+ if (llvm::GlobalVariable *GV =
+ CGM.getCXXABI().getThrowInfo(FD->getParamDecl(0)->getType()))
+ return RValue::get(llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy));
+ break;
+ }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
@@ -1763,7 +1876,12 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
return EmitPPCBuiltinExpr(BuiltinID, E);
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
- return EmitR600BuiltinExpr(BuiltinID, E);
+ return EmitAMDGPUBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::systemz:
+ return EmitSystemZBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ return EmitNVPTXBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
@@ -2534,7 +2652,7 @@ Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
// Return type.
SmallVector<llvm::Type *, 3> Tys;
if (Modifier & AddRetType) {
- llvm::Type *Ty = ConvertType(E->getCallReturnType());
+ llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext()));
if (Modifier & VectorizeRetType)
Ty = llvm::VectorType::get(
Ty, VectorSize ? VectorSize / Ty->getPrimitiveSizeInBits() : 1);
@@ -2812,7 +2930,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
// NEON intrinsic puts accumulator first, unlike the LLVM fma.
- return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]});
}
case NEON::BI__builtin_neon_vld1_v:
case NEON::BI__builtin_neon_vld1q_v:
@@ -2825,7 +2943,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vld4_v:
case NEON::BI__builtin_neon_vld4q_v: {
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Ty);
- Ops[1] = Builder.CreateCall2(F, Ops[1], Align, NameHint);
+ Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, NameHint);
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
return Builder.CreateStore(Ops[1], Ops[0]);
@@ -3004,7 +3122,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Indices.push_back(Builder.getInt32(i+vi));
Indices.push_back(Builder.getInt32(i+e+vi));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
SV = Builder.CreateStore(SV, Addr);
@@ -3032,7 +3150,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi));
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
SV = Builder.CreateStore(SV, Addr);
@@ -3052,7 +3170,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
SV = Builder.CreateStore(SV, Addr);
@@ -3163,6 +3281,102 @@ Value *CodeGenFunction::GetValueForARMHint(unsigned BuiltinID) {
}
}
+// Generates the IR for the read/write special register builtin,
+// ValueType is the type of the value that is to be written or read,
+// RegisterType is the type of the register being written to or read from.
+static Value *EmitSpecialRegisterBuiltin(CodeGenFunction &CGF,
+ const CallExpr *E,
+ llvm::Type *RegisterType,
+ llvm::Type *ValueType, bool IsRead) {
+ // write and register intrinsics only support 32 and 64 bit operations.
+ assert((RegisterType->isIntegerTy(32) || RegisterType->isIntegerTy(64))
+ && "Unsupported size for register.");
+
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ CodeGen::CodeGenModule &CGM = CGF.CGM;
+ LLVMContext &Context = CGM.getLLVMContext();
+
+ const Expr *SysRegStrExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef SysReg = cast<StringLiteral>(SysRegStrExpr)->getString();
+
+ llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysReg) };
+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+
+ llvm::Type *Types[] = { RegisterType };
+
+ bool MixedTypes = RegisterType->isIntegerTy(64) && ValueType->isIntegerTy(32);
+ assert(!(RegisterType->isIntegerTy(32) && ValueType->isIntegerTy(64))
+ && "Can't fit 64-bit value in 32-bit register");
+
+ if (IsRead) {
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
+ llvm::Value *Call = Builder.CreateCall(F, Metadata);
+
+ if (MixedTypes)
+ // Read into 64 bit register and then truncate result to 32 bit.
+ return Builder.CreateTrunc(Call, ValueType);
+
+ if (ValueType->isPointerTy())
+ // Have i32/i64 result (Call) but want to return a VoidPtrTy (i8*).
+ return Builder.CreateIntToPtr(Call, ValueType);
+
+ return Call;
+ }
+
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
+ llvm::Value *ArgValue = CGF.EmitScalarExpr(E->getArg(1));
+ if (MixedTypes) {
+ // Extend 32 bit write value to 64 bit to pass to write.
+ ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+ }
+
+ if (ValueType->isPointerTy()) {
+ // Have VoidPtrTy ArgValue but want to return an i32/i64.
+ ArgValue = Builder.CreatePtrToInt(ArgValue, RegisterType);
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+ }
+
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+}
+
+/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
+/// argument that specifies the vector type.
+static bool HasExtraNeonArgument(unsigned BuiltinID) {
+ switch (BuiltinID) {
+ default: break;
+ case NEON::BI__builtin_neon_vget_lane_i8:
+ case NEON::BI__builtin_neon_vget_lane_i16:
+ case NEON::BI__builtin_neon_vget_lane_i32:
+ case NEON::BI__builtin_neon_vget_lane_i64:
+ case NEON::BI__builtin_neon_vget_lane_f32:
+ case NEON::BI__builtin_neon_vgetq_lane_i8:
+ case NEON::BI__builtin_neon_vgetq_lane_i16:
+ case NEON::BI__builtin_neon_vgetq_lane_i32:
+ case NEON::BI__builtin_neon_vgetq_lane_i64:
+ case NEON::BI__builtin_neon_vgetq_lane_f32:
+ case NEON::BI__builtin_neon_vset_lane_i8:
+ case NEON::BI__builtin_neon_vset_lane_i16:
+ case NEON::BI__builtin_neon_vset_lane_i32:
+ case NEON::BI__builtin_neon_vset_lane_i64:
+ case NEON::BI__builtin_neon_vset_lane_f32:
+ case NEON::BI__builtin_neon_vsetq_lane_i8:
+ case NEON::BI__builtin_neon_vsetq_lane_i16:
+ case NEON::BI__builtin_neon_vsetq_lane_i32:
+ case NEON::BI__builtin_neon_vsetq_lane_i64:
+ case NEON::BI__builtin_neon_vsetq_lane_f32:
+ case NEON::BI__builtin_neon_vsha1h_u32:
+ case NEON::BI__builtin_neon_vsha1cq_u32:
+ case NEON::BI__builtin_neon_vsha1pq_u32:
+ case NEON::BI__builtin_neon_vsha1mq_u32:
+ case ARM::BI_MoveToCoprocessor:
+ case ARM::BI_MoveToCoprocessor2:
+ return false;
+ }
+ return true;
+}
+
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (auto Hint = GetValueForARMHint(BuiltinID))
@@ -3202,7 +3416,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Value *Locality = llvm::ConstantInt::get(Int32Ty, 3);
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
- return Builder.CreateCall4(F, Address, RW, Locality, IsData);
+ return Builder.CreateCall(F, {Address, RW, Locality, IsData});
}
if (BuiltinID == ARM::BI__builtin_arm_rbit) {
@@ -3300,7 +3514,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Value *Arg0 = Builder.CreateExtractValue(Val, 0);
Value *Arg1 = Builder.CreateExtractValue(Val, 1);
Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), Int8PtrTy);
- return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "strexd");
+ return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "strexd");
}
if (BuiltinID == ARM::BI__builtin_arm_strex ||
@@ -3324,7 +3538,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
? Intrinsic::arm_stlex
: Intrinsic::arm_strex,
StoreAddr->getType());
- return Builder.CreateCall2(F, StoreVal, StoreAddr, "strex");
+ return Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex");
}
if (BuiltinID == ARM::BI__builtin_arm_clrex) {
@@ -3365,19 +3579,59 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Arg1b = Builder.CreateTruncOrBitCast(Arg1b, Int32Ty);
Function *F = CGM.getIntrinsic(CRCIntrinsicID);
- Value *Res = Builder.CreateCall2(F, Arg0, Arg1a);
- return Builder.CreateCall2(F, Res, Arg1b);
+ Value *Res = Builder.CreateCall(F, {Arg0, Arg1a});
+ return Builder.CreateCall(F, {Res, Arg1b});
} else {
Arg1 = Builder.CreateZExtOrBitCast(Arg1, Int32Ty);
Function *F = CGM.getIntrinsic(CRCIntrinsicID);
- return Builder.CreateCall2(F, Arg0, Arg1);
+ return Builder.CreateCall(F, {Arg0, Arg1});
+ }
+ }
+
+ if (BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp) {
+
+ bool IsRead = BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp;
+
+ bool IsPointerBuiltin = BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp;
+
+ bool Is64Bit = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64;
+
+ llvm::Type *ValueType;
+ llvm::Type *RegisterType;
+ if (IsPointerBuiltin) {
+ ValueType = VoidPtrTy;
+ RegisterType = Int32Ty;
+ } else if (Is64Bit) {
+ ValueType = RegisterType = Int64Ty;
+ } else {
+ ValueType = RegisterType = Int32Ty;
}
+
+ return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
}
+ // Find out if any arguments are required to be integer constant
+ // expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ assert(Error == ASTContext::GE_None && "Should not codegen an error");
+
SmallVector<Value*, 4> Ops;
llvm::Value *Align = nullptr;
- for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
+ bool HasExtraArg = HasExtraNeonArgument(BuiltinID);
+ unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
+ for (unsigned i = 0, e = NumArgs; i != e; i++) {
if (i == 0) {
switch (BuiltinID) {
case NEON::BI__builtin_neon_vld1_v:
@@ -3437,13 +3691,22 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
continue;
}
}
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
+
+ if ((ICEArguments & (1 << i)) == 0) {
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ } else {
+ // If this is required to be a constant, constant fold it so that we know
+ // that the generated intrinsic gets a ConstantInt.
+ llvm::APSInt Result;
+ bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext());
+ assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst;
+ Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result));
+ }
}
switch (BuiltinID) {
default: break;
- // vget_lane and vset_lane are not overloaded and do not have an extra
- // argument that specifies the vector type.
+
case NEON::BI__builtin_neon_vget_lane_i8:
case NEON::BI__builtin_neon_vget_lane_i16:
case NEON::BI__builtin_neon_vget_lane_i32:
@@ -3454,8 +3717,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vgetq_lane_i32:
case NEON::BI__builtin_neon_vgetq_lane_i64:
case NEON::BI__builtin_neon_vgetq_lane_f32:
- return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
- "vget_lane");
+ return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane");
+
case NEON::BI__builtin_neon_vset_lane_i8:
case NEON::BI__builtin_neon_vset_lane_i16:
case NEON::BI__builtin_neon_vset_lane_i32:
@@ -3466,29 +3729,34 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vsetq_lane_i32:
case NEON::BI__builtin_neon_vsetq_lane_i64:
case NEON::BI__builtin_neon_vsetq_lane_f32:
- Ops.push_back(EmitScalarExpr(E->getArg(2)));
return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
- // Non-polymorphic crypto instructions also not overloaded
case NEON::BI__builtin_neon_vsha1h_u32:
- Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1h), Ops,
"vsha1h");
case NEON::BI__builtin_neon_vsha1cq_u32:
- Ops.push_back(EmitScalarExpr(E->getArg(2)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1c), Ops,
"vsha1h");
case NEON::BI__builtin_neon_vsha1pq_u32:
- Ops.push_back(EmitScalarExpr(E->getArg(2)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1p), Ops,
"vsha1h");
case NEON::BI__builtin_neon_vsha1mq_u32:
- Ops.push_back(EmitScalarExpr(E->getArg(2)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1m), Ops,
"vsha1h");
+
+ // The ARM _MoveToCoprocessor builtins put the input register value as
+ // the first argument, but the LLVM intrinsic expects it as the third one.
+ case ARM::BI_MoveToCoprocessor:
+ case ARM::BI_MoveToCoprocessor2: {
+ Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI_MoveToCoprocessor ?
+ Intrinsic::arm_mcr : Intrinsic::arm_mcr2);
+ return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0],
+ Ops[3], Ops[4], Ops[5]});
+ }
}
// Get the last argument, which specifies the vector type.
+ assert(HasExtraArg);
llvm::APSInt Result;
const Expr *Arg = E->getArg(E->getNumArgs()-1);
if (!Arg->isIntegerConstantExpr(Result, getContext()))
@@ -3547,7 +3815,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
// Load the value as a one-element vector.
Ty = llvm::VectorType::get(VTy->getElementType(), 1);
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Ty);
- Value *Ld = Builder.CreateCall2(F, Ops[0], Align);
+ Value *Ld = Builder.CreateCall(F, {Ops[0], Align});
// Combine them.
SmallVector<Constant*, 2> Indices;
Indices.push_back(ConstantInt::get(Int32Ty, 1-Lane));
@@ -3582,7 +3850,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
default: llvm_unreachable("unknown vld_dup intrinsic?");
}
Function *F = CGM.getIntrinsic(Int, Ty);
- Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup");
+ Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, "vld_dup");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
return Builder.CreateStore(Ops[1], Ops[0]);
@@ -3651,7 +3919,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = EmitNeonShiftVector(Ops[2], Ty, true);
Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts;
- Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Ty), Ops[1], Ops[2]);
+ Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Ty), {Ops[1], Ops[2]});
return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n");
case NEON::BI__builtin_neon_vsri_n_v:
case NEON::BI__builtin_neon_vsriq_n_v:
@@ -3897,38 +4165,6 @@ Value *CodeGenFunction::vectorWrapScalar8(Value *Op) {
return Op;
}
-Value *CodeGenFunction::
-emitVectorWrappedScalar8Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
- const char *Name) {
- // i8 is not a legal types for AArch64, so we can't just use
- // a normal overloaded intrinsic call for these scalar types. Instead
- // we'll build 64-bit vectors w/ lane zero being our input values and
- // perform the operation on that. The back end can pattern match directly
- // to the scalar instruction.
- Ops[0] = vectorWrapScalar8(Ops[0]);
- Ops[1] = vectorWrapScalar8(Ops[1]);
- llvm::Type *VTy = llvm::VectorType::get(Int8Ty, 8);
- Value *V = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, Name);
- Constant *CI = ConstantInt::get(SizeTy, 0);
- return Builder.CreateExtractElement(V, CI, "lane0");
-}
-
-Value *CodeGenFunction::
-emitVectorWrappedScalar16Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
- const char *Name) {
- // i16 is not a legal types for AArch64, so we can't just use
- // a normal overloaded intrinsic call for these scalar types. Instead
- // we'll build 64-bit vectors w/ lane zero being our input values and
- // perform the operation on that. The back end can pattern match directly
- // to the scalar instruction.
- Ops[0] = vectorWrapScalar16(Ops[0]);
- Ops[1] = vectorWrapScalar16(Ops[1]);
- llvm::Type *VTy = llvm::VectorType::get(Int16Ty, 4);
- Value *V = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, Name);
- Constant *CI = ConstantInt::get(SizeTy, 0);
- return Builder.CreateExtractElement(V, CI, "lane0");
-}
-
Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
unsigned HintID = static_cast<unsigned>(-1);
@@ -3979,7 +4215,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
// FIXME: We need AArch64 specific LLVM intrinsic if we want to specify
// PLDL3STRM or PLDL2STRM.
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
- return Builder.CreateCall4(F, Address, RW, Locality, IsData);
+ return Builder.CreateCall(F, {Address, RW, Locality, IsData});
}
if (BuiltinID == AArch64::BI__builtin_arm_rbit) {
@@ -4074,9 +4310,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Arg1 = Builder.CreateExtractValue(Val, 1);
Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)),
Int8PtrTy);
- return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "stxp");
- } else if (BuiltinID == AArch64::BI__builtin_arm_strex ||
- BuiltinID == AArch64::BI__builtin_arm_stlex) {
+ return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "stxp");
+ }
+
+ if (BuiltinID == AArch64::BI__builtin_arm_strex ||
+ BuiltinID == AArch64::BI__builtin_arm_stlex) {
Value *StoreVal = EmitScalarExpr(E->getArg(0));
Value *StoreAddr = EmitScalarExpr(E->getArg(1));
@@ -4096,7 +4334,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
? Intrinsic::aarch64_stlxr
: Intrinsic::aarch64_stxr,
StoreAddr->getType());
- return Builder.CreateCall2(F, StoreVal, StoreAddr, "stxr");
+ return Builder.CreateCall(F, {StoreVal, StoreAddr}, "stxr");
}
if (BuiltinID == AArch64::BI__builtin_arm_clrex) {
@@ -4133,12 +4371,60 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *DataTy = F->getFunctionType()->getParamType(1);
Arg1 = Builder.CreateZExtOrBitCast(Arg1, DataTy);
- return Builder.CreateCall2(F, Arg0, Arg1);
+ return Builder.CreateCall(F, {Arg0, Arg1});
+ }
+
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp) {
+
+ bool IsRead = BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp;
+
+ bool IsPointerBuiltin = BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp;
+
+ bool Is64Bit = BuiltinID != AArch64::BI__builtin_arm_rsr &&
+ BuiltinID != AArch64::BI__builtin_arm_wsr;
+
+ llvm::Type *ValueType;
+ llvm::Type *RegisterType = Int64Ty;
+ if (IsPointerBuiltin) {
+ ValueType = VoidPtrTy;
+ } else if (Is64Bit) {
+ ValueType = Int64Ty;
+ } else {
+ ValueType = Int32Ty;
+ }
+
+ return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
}
+ // Find out if any arguments are required to be integer constant
+ // expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ assert(Error == ASTContext::GE_None && "Should not codegen an error");
+
llvm::SmallVector<Value*, 4> Ops;
- for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++)
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
+ if ((ICEArguments & (1 << i)) == 0) {
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ } else {
+ // If this is required to be a constant, constant fold it so that we know
+ // that the generated intrinsic gets a ConstantInt.
+ llvm::APSInt Result;
+ bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext());
+ assert(IsConst && "Constant arg isn't actually constant?");
+ (void)IsConst;
+ Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result));
+ }
+ }
auto SISDMap = makeArrayRef(AArch64SISDIntrinsicMap);
const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap(
@@ -4248,36 +4534,36 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vceqzs_f32:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
- Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OEQ,
- ICmpInst::ICMP_EQ, "vceqz");
+ Ops[0], ConvertType(E->getCallReturnType(getContext())),
+ ICmpInst::FCMP_OEQ, ICmpInst::ICMP_EQ, "vceqz");
case NEON::BI__builtin_neon_vcgezd_s64:
case NEON::BI__builtin_neon_vcgezd_f64:
case NEON::BI__builtin_neon_vcgezs_f32:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
- Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OGE,
- ICmpInst::ICMP_SGE, "vcgez");
+ Ops[0], ConvertType(E->getCallReturnType(getContext())),
+ ICmpInst::FCMP_OGE, ICmpInst::ICMP_SGE, "vcgez");
case NEON::BI__builtin_neon_vclezd_s64:
case NEON::BI__builtin_neon_vclezd_f64:
case NEON::BI__builtin_neon_vclezs_f32:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
- Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OLE,
- ICmpInst::ICMP_SLE, "vclez");
+ Ops[0], ConvertType(E->getCallReturnType(getContext())),
+ ICmpInst::FCMP_OLE, ICmpInst::ICMP_SLE, "vclez");
case NEON::BI__builtin_neon_vcgtzd_s64:
case NEON::BI__builtin_neon_vcgtzd_f64:
case NEON::BI__builtin_neon_vcgtzs_f32:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
- Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OGT,
- ICmpInst::ICMP_SGT, "vcgtz");
+ Ops[0], ConvertType(E->getCallReturnType(getContext())),
+ ICmpInst::FCMP_OGT, ICmpInst::ICMP_SGT, "vcgtz");
case NEON::BI__builtin_neon_vcltzd_s64:
case NEON::BI__builtin_neon_vcltzd_f64:
case NEON::BI__builtin_neon_vcltzs_f32:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitAArch64CompareBuiltinExpr(
- Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OLT,
- ICmpInst::ICMP_SLT, "vcltz");
+ Ops[0], ConvertType(E->getCallReturnType(getContext())),
+ ICmpInst::FCMP_OLT, ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vceqzd_u64: {
llvm::Type *Ty = llvm::Type::getInt64Ty(getLLVMContext());
@@ -4528,8 +4814,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
: Intrinsic::aarch64_neon_srshl;
Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
Ops.push_back(Builder.CreateNeg(EmitScalarExpr(E->getArg(2))));
- Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Int64Ty), Ops[1],
- Builder.CreateSExt(Ops[2], Int64Ty));
+ Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Int64Ty),
+ {Ops[1], Builder.CreateSExt(Ops[2], Int64Ty)});
return Builder.CreateAdd(Ops[0], Builder.CreateBitCast(Ops[1], Int64Ty));
}
case NEON::BI__builtin_neon_vshld_n_s64:
@@ -4699,7 +4985,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
- Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ Value *Result = Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]});
return Builder.CreateBitCast(Result, Ty);
}
Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
@@ -4713,7 +4999,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
cast<ConstantInt>(Ops[3]));
Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]});
}
case NEON::BI__builtin_neon_vfmaq_laneq_v: {
Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
@@ -4722,17 +5008,17 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
- return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]});
}
case NEON::BI__builtin_neon_vfmas_lane_f32:
case NEON::BI__builtin_neon_vfmas_laneq_f32:
case NEON::BI__builtin_neon_vfmad_lane_f64:
case NEON::BI__builtin_neon_vfmad_laneq_f64: {
Ops.push_back(EmitScalarExpr(E->getArg(3)));
- llvm::Type *Ty = ConvertType(E->getCallReturnType());
+ llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext()));
Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
- return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]});
}
case NEON::BI__builtin_neon_vfms_v:
case NEON::BI__builtin_neon_vfmsq_v: { // Only used for FP types
@@ -5667,7 +5953,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Indices.push_back(ConstantInt::get(Int32Ty, i+vi));
Indices.push_back(ConstantInt::get(Int32Ty, i+e+vi));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
SV = Builder.CreateStore(SV, Addr);
@@ -5686,7 +5972,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi));
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
SV = Builder.CreateStore(SV, Addr);
@@ -5706,7 +5992,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
}
- Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
SV = Builder.CreateStore(SV, Addr);
@@ -5811,13 +6097,90 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
switch (BuiltinID) {
default: return nullptr;
+ case X86::BI__builtin_cpu_supports: {
+ const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString();
+
+ // TODO: When/if this becomes more than x86 specific then use a TargetInfo
+ // based mapping.
+ // Processor features and mapping to processor feature value.
+ enum X86Features {
+ CMOV = 0,
+ MMX,
+ POPCNT,
+ SSE,
+ SSE2,
+ SSE3,
+ SSSE3,
+ SSE4_1,
+ SSE4_2,
+ AVX,
+ AVX2,
+ SSE4_A,
+ FMA4,
+ XOP,
+ FMA,
+ AVX512F,
+ BMI,
+ BMI2,
+ MAX
+ };
+
+ X86Features Feature = StringSwitch<X86Features>(FeatureStr)
+ .Case("cmov", X86Features::CMOV)
+ .Case("mmx", X86Features::MMX)
+ .Case("popcnt", X86Features::POPCNT)
+ .Case("sse", X86Features::SSE)
+ .Case("sse2", X86Features::SSE2)
+ .Case("sse3", X86Features::SSE3)
+ .Case("sse4.1", X86Features::SSE4_1)
+ .Case("sse4.2", X86Features::SSE4_2)
+ .Case("avx", X86Features::AVX)
+ .Case("avx2", X86Features::AVX2)
+ .Case("sse4a", X86Features::SSE4_A)
+ .Case("fma4", X86Features::FMA4)
+ .Case("xop", X86Features::XOP)
+ .Case("fma", X86Features::FMA)
+ .Case("avx512f", X86Features::AVX512F)
+ .Case("bmi", X86Features::BMI)
+ .Case("bmi2", X86Features::BMI2)
+ .Default(X86Features::MAX);
+ assert(Feature != X86Features::MAX && "Invalid feature!");
+
+ // Matching the struct layout from the compiler-rt/libgcc structure that is
+ // filled in:
+ // unsigned int __cpu_vendor;
+ // unsigned int __cpu_type;
+ // unsigned int __cpu_subtype;
+ // unsigned int __cpu_features[1];
+ llvm::Type *STy = llvm::StructType::get(
+ Int32Ty, Int32Ty, Int32Ty, llvm::ArrayType::get(Int32Ty, 1), nullptr);
+
+ // Grab the global __cpu_model.
+ llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+
+ // Grab the first (0th) element from the field __cpu_features off of the
+ // global in the struct STy.
+ Value *Idxs[] = {
+ ConstantInt::get(Int32Ty, 0),
+ ConstantInt::get(Int32Ty, 3),
+ ConstantInt::get(Int32Ty, 0)
+ };
+ Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
+ Value *Features = Builder.CreateLoad(CpuFeatures);
+
+ // Check the value of the bit corresponding to the feature requested.
+ Value *Bitset = Builder.CreateAnd(
+ Features, llvm::ConstantInt::get(Int32Ty, 1 << Feature));
+ return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
+ }
case X86::BI_mm_prefetch: {
Value *Address = EmitScalarExpr(E->getArg(0));
Value *RW = ConstantInt::get(Int32Ty, 0);
Value *Locality = EmitScalarExpr(E->getArg(1));
Value *Data = ConstantInt::get(Int32Ty, 1);
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
- return Builder.CreateCall4(F, Address, RW, Locality, Data);
+ return Builder.CreateCall(F, {Address, RW, Locality, Data});
}
case X86::BI__builtin_ia32_vec_init_v8qi:
case X86::BI__builtin_ia32_vec_init_v4hi:
@@ -5856,104 +6219,95 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
return Builder.CreateStore(Ops[1], Ops[0]);
}
- case X86::BI__builtin_ia32_palignr: {
- unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
-
- // If palignr is shifting the pair of input vectors less than 9 bytes,
- // emit a shuffle instruction.
- if (shiftVal <= 8) {
- SmallVector<llvm::Constant*, 8> Indices;
- for (unsigned i = 0; i != 8; ++i)
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i));
-
- Value* SV = llvm::ConstantVector::get(Indices);
- return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
+ case X86::BI__builtin_ia32_palignr128:
+ case X86::BI__builtin_ia32_palignr256: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+
+ unsigned NumElts =
+ cast<llvm::VectorType>(Ops[0]->getType())->getNumElements();
+ assert(NumElts % 16 == 0);
+ unsigned NumLanes = NumElts / 16;
+ unsigned NumLaneElts = NumElts / NumLanes;
+
+ // If palignr is shifting the pair of vectors more than the size of two
+ // lanes, emit zero.
+ if (ShiftVal >= (2 * NumLaneElts))
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
+
+ // If palignr is shifting the pair of input vectors more than one lane,
+ // but less than two lanes, convert to shifting in zeroes.
+ if (ShiftVal > NumLaneElts) {
+ ShiftVal -= NumLaneElts;
+ Ops[0] = llvm::Constant::getNullValue(Ops[0]->getType());
}
- // If palignr is shifting the pair of input vectors more than 8 but less
- // than 16 bytes, emit a logical right shift of the destination.
- if (shiftVal < 16) {
- // MMX has these as 1 x i64 vectors for some odd optimization reasons.
- llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 1);
-
- Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
- Ops[1] = llvm::ConstantInt::get(VecTy, (shiftVal-8) * 8);
-
- // create i32 constant
- llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_mmx_psrl_q);
- return Builder.CreateCall(F, makeArrayRef(Ops.data(), 2), "palignr");
+ SmallVector<llvm::Constant*, 32> Indices;
+ // 256-bit palignr operates on 128-bit lanes so we need to handle that
+ for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
+ for (unsigned i = 0; i != NumLaneElts; ++i) {
+ unsigned Idx = ShiftVal + i;
+ if (Idx >= NumLaneElts)
+ Idx += NumElts - NumLaneElts; // End of lane, switch operand.
+ Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
+ }
}
- // If palignr is shifting the pair of vectors more than 16 bytes, emit zero.
- return llvm::Constant::getNullValue(ConvertType(E->getType()));
+ Value* SV = llvm::ConstantVector::get(Indices);
+ return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
}
- case X86::BI__builtin_ia32_palignr128: {
- unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+ case X86::BI__builtin_ia32_pslldqi256: {
+ // Shift value is in bits so divide by 8.
+ unsigned shiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() >> 3;
- // If palignr is shifting the pair of input vectors less than 17 bytes,
- // emit a shuffle instruction.
- if (shiftVal <= 16) {
- SmallVector<llvm::Constant*, 16> Indices;
- for (unsigned i = 0; i != 16; ++i)
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i));
+ // If pslldq is shifting the vector more than 15 bytes, emit zero.
+ if (shiftVal >= 16)
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
- Value* SV = llvm::ConstantVector::get(Indices);
- return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
+ SmallVector<llvm::Constant*, 32> Indices;
+ // 256-bit pslldq operates on 128-bit lanes so we need to handle that
+ for (unsigned l = 0; l != 32; l += 16) {
+ for (unsigned i = 0; i != 16; ++i) {
+ unsigned Idx = 32 + i - shiftVal;
+ if (Idx < 32) Idx -= 16; // end of lane, switch operand.
+ Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
+ }
}
- // If palignr is shifting the pair of input vectors more than 16 but less
- // than 32 bytes, emit a logical right shift of the destination.
- if (shiftVal < 32) {
- llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2);
-
- Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
- Ops[1] = llvm::ConstantInt::get(Int32Ty, (shiftVal-16) * 8);
-
- // create i32 constant
- llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_psrl_dq);
- return Builder.CreateCall(F, makeArrayRef(Ops.data(), 2), "palignr");
- }
+ llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, 32);
+ Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Value *Zero = llvm::Constant::getNullValue(VecTy);
- // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
- return llvm::Constant::getNullValue(ConvertType(E->getType()));
- }
- case X86::BI__builtin_ia32_palignr256: {
- unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
-
- // If palignr is shifting the pair of input vectors less than 17 bytes,
- // emit a shuffle instruction.
- if (shiftVal <= 16) {
- SmallVector<llvm::Constant*, 32> Indices;
- // 256-bit palignr operates on 128-bit lanes so we need to handle that
- for (unsigned l = 0; l != 2; ++l) {
- unsigned LaneStart = l * 16;
- unsigned LaneEnd = (l+1) * 16;
- for (unsigned i = 0; i != 16; ++i) {
- unsigned Idx = shiftVal + i + LaneStart;
- if (Idx >= LaneEnd) Idx += 16; // end of lane, switch operand
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx));
- }
+ Value *SV = llvm::ConstantVector::get(Indices);
+ SV = Builder.CreateShuffleVector(Zero, Ops[0], SV, "pslldq");
+ llvm::Type *ResultType = ConvertType(E->getType());
+ return Builder.CreateBitCast(SV, ResultType, "cast");
+ }
+ case X86::BI__builtin_ia32_psrldqi256: {
+ // Shift value is in bits so divide by 8.
+ unsigned shiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() >> 3;
+
+ // If psrldq is shifting the vector more than 15 bytes, emit zero.
+ if (shiftVal >= 16)
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
+
+ SmallVector<llvm::Constant*, 32> Indices;
+ // 256-bit psrldq operates on 128-bit lanes so we need to handle that
+ for (unsigned l = 0; l != 32; l += 16) {
+ for (unsigned i = 0; i != 16; ++i) {
+ unsigned Idx = i + shiftVal;
+ if (Idx >= 16) Idx += 16; // end of lane, switch operand.
+ Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
}
-
- Value* SV = llvm::ConstantVector::get(Indices);
- return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
}
- // If palignr is shifting the pair of input vectors more than 16 but less
- // than 32 bytes, emit a logical right shift of the destination.
- if (shiftVal < 32) {
- llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 4);
+ llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, 32);
+ Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Value *Zero = llvm::Constant::getNullValue(VecTy);
- Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
- Ops[1] = llvm::ConstantInt::get(Int32Ty, (shiftVal-16) * 8);
-
- // create i32 constant
- llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_avx2_psrl_dq);
- return Builder.CreateCall(F, makeArrayRef(Ops.data(), 2), "palignr");
- }
-
- // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
- return llvm::Constant::getNullValue(ConvertType(E->getType()));
+ Value *SV = llvm::ConstantVector::get(Indices);
+ SV = Builder.CreateShuffleVector(Ops[0], Zero, SV, "psrldq");
+ llvm::Type *ResultType = ConvertType(E->getType());
+ return Builder.CreateBitCast(SV, ResultType, "cast");
}
case X86::BI__builtin_ia32_movntps:
case X86::BI__builtin_ia32_movntps256:
@@ -5987,20 +6341,10 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
// 3DNow!
case X86::BI__builtin_ia32_pswapdsf:
case X86::BI__builtin_ia32_pswapdsi: {
- const char *name;
- Intrinsic::ID ID;
- switch(BuiltinID) {
- default: llvm_unreachable("Unsupported intrinsic!");
- case X86::BI__builtin_ia32_pswapdsf:
- case X86::BI__builtin_ia32_pswapdsi:
- name = "pswapd";
- ID = Intrinsic::x86_3dnowa_pswapd;
- break;
- }
llvm::Type *MMXTy = llvm::Type::getX86_MMXTy(getLLVMContext());
Ops[0] = Builder.CreateBitCast(Ops[0], MMXTy, "cast");
- llvm::Function *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Ops, name);
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_3dnowa_pswapd);
+ return Builder.CreateCall(F, Ops, "pswapd");
}
case X86::BI__builtin_ia32_rdrand16_step:
case X86::BI__builtin_ia32_rdrand32_step:
@@ -6035,13 +6379,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
- // AVX2 broadcast
- case X86::BI__builtin_ia32_vbroadcastsi256: {
- Value *VecTmp = CreateMemTemp(E->getArg(0)->getType());
- Builder.CreateStore(Ops[0], VecTmp);
- Value *F = CGM.getIntrinsic(Intrinsic::x86_avx2_vbroadcasti128);
- return Builder.CreateCall(F, Builder.CreateBitCast(VecTmp, Int8PtrTy));
- }
// SSE comparison intrisics
case X86::BI__builtin_ia32_cmpeqps:
case X86::BI__builtin_ia32_cmpltps:
@@ -6296,6 +6633,103 @@ 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));
+ 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
+ }
}
}
@@ -6318,7 +6752,7 @@ static Value *emitTernaryFPBuiltin(CodeGenFunction &CGF,
llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2));
Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
- return CGF.Builder.CreateCall3(F, Src0, Src1, Src2);
+ return CGF.Builder.CreateCall(F, {Src0, Src1, Src2});
}
// Emit an intrinsic that has 1 float or double operand, and 1 integer.
@@ -6329,14 +6763,14 @@ static Value *emitFPIntBuiltin(CodeGenFunction &CGF,
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
- return CGF.Builder.CreateCall2(F, Src0, Src1);
+ return CGF.Builder.CreateCall(F, {Src0, Src1});
}
-Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
+Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
switch (BuiltinID) {
- case R600::BI__builtin_amdgpu_div_scale:
- case R600::BI__builtin_amdgpu_div_scalef: {
+ case AMDGPU::BI__builtin_amdgpu_div_scale:
+ case AMDGPU::BI__builtin_amdgpu_div_scalef: {
// Translate from the intrinsics's struct return to the builtin's out
// argument.
@@ -6350,7 +6784,7 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
llvm::Value *Callee = CGM.getIntrinsic(Intrinsic::AMDGPU_div_scale,
X->getType());
- llvm::Value *Tmp = Builder.CreateCall3(Callee, X, Y, Z);
+ llvm::Value *Tmp = Builder.CreateCall(Callee, {X, Y, Z});
llvm::Value *Result = Builder.CreateExtractValue(Tmp, 0);
llvm::Value *Flag = Builder.CreateExtractValue(Tmp, 1);
@@ -6363,8 +6797,8 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
FlagStore->setAlignment(FlagOutPtr.second);
return Result;
}
- case R600::BI__builtin_amdgpu_div_fmas:
- case R600::BI__builtin_amdgpu_div_fmasf: {
+ case AMDGPU::BI__builtin_amdgpu_div_fmas:
+ case AMDGPU::BI__builtin_amdgpu_div_fmasf: {
llvm::Value *Src0 = EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
llvm::Value *Src2 = EmitScalarExpr(E->getArg(2));
@@ -6373,30 +6807,342 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
llvm::Value *F = CGM.getIntrinsic(Intrinsic::AMDGPU_div_fmas,
Src0->getType());
llvm::Value *Src3ToBool = Builder.CreateIsNotNull(Src3);
- return Builder.CreateCall4(F, Src0, Src1, Src2, Src3ToBool);
+ return Builder.CreateCall(F, {Src0, Src1, Src2, Src3ToBool});
}
- case R600::BI__builtin_amdgpu_div_fixup:
- case R600::BI__builtin_amdgpu_div_fixupf:
+ case AMDGPU::BI__builtin_amdgpu_div_fixup:
+ case AMDGPU::BI__builtin_amdgpu_div_fixupf:
return emitTernaryFPBuiltin(*this, E, Intrinsic::AMDGPU_div_fixup);
- case R600::BI__builtin_amdgpu_trig_preop:
- case R600::BI__builtin_amdgpu_trig_preopf:
+ case AMDGPU::BI__builtin_amdgpu_trig_preop:
+ case AMDGPU::BI__builtin_amdgpu_trig_preopf:
return emitFPIntBuiltin(*this, E, Intrinsic::AMDGPU_trig_preop);
- case R600::BI__builtin_amdgpu_rcp:
- case R600::BI__builtin_amdgpu_rcpf:
+ case AMDGPU::BI__builtin_amdgpu_rcp:
+ case AMDGPU::BI__builtin_amdgpu_rcpf:
return emitUnaryFPBuiltin(*this, E, Intrinsic::AMDGPU_rcp);
- case R600::BI__builtin_amdgpu_rsq:
- case R600::BI__builtin_amdgpu_rsqf:
+ case AMDGPU::BI__builtin_amdgpu_rsq:
+ case AMDGPU::BI__builtin_amdgpu_rsqf:
return emitUnaryFPBuiltin(*this, E, Intrinsic::AMDGPU_rsq);
- case R600::BI__builtin_amdgpu_rsq_clamped:
- case R600::BI__builtin_amdgpu_rsq_clampedf:
+ case AMDGPU::BI__builtin_amdgpu_rsq_clamped:
+ case AMDGPU::BI__builtin_amdgpu_rsq_clampedf:
return emitUnaryFPBuiltin(*this, E, Intrinsic::AMDGPU_rsq_clamped);
- case R600::BI__builtin_amdgpu_ldexp:
- case R600::BI__builtin_amdgpu_ldexpf:
+ case AMDGPU::BI__builtin_amdgpu_ldexp:
+ case AMDGPU::BI__builtin_amdgpu_ldexpf:
return emitFPIntBuiltin(*this, E, Intrinsic::AMDGPU_ldexp);
- case R600::BI__builtin_amdgpu_class:
- case R600::BI__builtin_amdgpu_classf:
+ case AMDGPU::BI__builtin_amdgpu_class:
+ case AMDGPU::BI__builtin_amdgpu_classf:
return emitFPIntBuiltin(*this, E, Intrinsic::AMDGPU_class);
default:
return nullptr;
}
}
+
+/// Handle a SystemZ function in which the final argument is a pointer
+/// to an int that receives the post-instruction CC value. At the LLVM level
+/// this is represented as a function that returns a {result, cc} pair.
+static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction &CGF,
+ unsigned IntrinsicID,
+ const CallExpr *E) {
+ unsigned NumArgs = E->getNumArgs() - 1;
+ SmallVector<Value *, 8> Args(NumArgs);
+ for (unsigned I = 0; I < NumArgs; ++I)
+ Args[I] = CGF.EmitScalarExpr(E->getArg(I));
+ Value *CCPtr = CGF.EmitScalarExpr(E->getArg(NumArgs));
+ Value *F = CGF.CGM.getIntrinsic(IntrinsicID);
+ Value *Call = CGF.Builder.CreateCall(F, Args);
+ Value *CC = CGF.Builder.CreateExtractValue(Call, 1);
+ CGF.Builder.CreateStore(CC, CCPtr);
+ return CGF.Builder.CreateExtractValue(Call, 0);
+}
+
+Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case SystemZ::BI__builtin_tbegin: {
+ Value *TDB = EmitScalarExpr(E->getArg(0));
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin);
+ return Builder.CreateCall(F, {TDB, Control});
+ }
+ case SystemZ::BI__builtin_tbegin_nofloat: {
+ Value *TDB = EmitScalarExpr(E->getArg(0));
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat);
+ return Builder.CreateCall(F, {TDB, Control});
+ }
+ case SystemZ::BI__builtin_tbeginc: {
+ Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy);
+ Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08);
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc);
+ return Builder.CreateCall(F, {TDB, Control});
+ }
+ case SystemZ::BI__builtin_tabort: {
+ Value *Data = EmitScalarExpr(E->getArg(0));
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_tabort);
+ return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort"));
+ }
+ case SystemZ::BI__builtin_non_tx_store: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Data = EmitScalarExpr(E->getArg(1));
+ Value *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);
+ return Builder.CreateCall(F, {Data, Address});
+ }
+
+ // Vector builtins. Note that most vector builtins are mapped automatically
+ // to target-specific LLVM intrinsics. The ones handled specially here can
+ // be represented via standard LLVM IR, which is preferable to enable common
+ // LLVM optimizations.
+
+ case SystemZ::BI__builtin_s390_vpopctb:
+ case SystemZ::BI__builtin_s390_vpopcth:
+ case SystemZ::BI__builtin_s390_vpopctf:
+ case SystemZ::BI__builtin_s390_vpopctg: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+
+ case SystemZ::BI__builtin_s390_vclzb:
+ case SystemZ::BI__builtin_s390_vclzh:
+ case SystemZ::BI__builtin_s390_vclzf:
+ case SystemZ::BI__builtin_s390_vclzg: {
+ 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});
+ }
+
+ case SystemZ::BI__builtin_s390_vctzb:
+ case SystemZ::BI__builtin_s390_vctzh:
+ case SystemZ::BI__builtin_s390_vctzf:
+ case SystemZ::BI__builtin_s390_vctzg: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
+ Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);
+ return Builder.CreateCall(F, {X, Undef});
+ }
+
+ case SystemZ::BI__builtin_s390_vfsqdb: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+ case SystemZ::BI__builtin_s390_vfmadb: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Y = EmitScalarExpr(E->getArg(1));
+ Value *Z = EmitScalarExpr(E->getArg(2));
+ Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
+ return Builder.CreateCall(F, {X, Y, Z});
+ }
+ case SystemZ::BI__builtin_s390_vfmsdb: {
+ 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);
+ Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
+ return Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")});
+ }
+ case SystemZ::BI__builtin_s390_vflpdb: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+ case SystemZ::BI__builtin_s390_vflndb: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType);
+ Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
+ return Builder.CreateFSub(Zero, Builder.CreateCall(F, X), "sub");
+ }
+ case SystemZ::BI__builtin_s390_vfidb: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ // Constant-fold the M4 and M5 mask arguments.
+ llvm::APSInt M4, M5;
+ bool IsConstM4 = E->getArg(1)->isIntegerConstantExpr(M4, getContext());
+ bool IsConstM5 = E->getArg(2)->isIntegerConstantExpr(M5, getContext());
+ assert(IsConstM4 && IsConstM5 && "Constant arg isn't actually constant?");
+ (void)IsConstM4; (void)IsConstM5;
+ // Check whether this instance of vfidb can be represented via a LLVM
+ // standard intrinsic. We only support some combinations of M4 and M5.
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+ switch (M4.getZExtValue()) {
+ default: break;
+ case 0: // IEEE-inexact exception allowed
+ switch (M5.getZExtValue()) {
+ default: break;
+ case 0: ID = Intrinsic::rint; break;
+ }
+ break;
+ case 4: // IEEE-inexact exception suppressed
+ switch (M5.getZExtValue()) {
+ default: break;
+ case 0: ID = Intrinsic::nearbyint; break;
+ case 1: ID = Intrinsic::round; break;
+ case 5: ID = Intrinsic::trunc; break;
+ case 6: ID = Intrinsic::ceil; break;
+ case 7: ID = Intrinsic::floor; break;
+ }
+ break;
+ }
+ if (ID != Intrinsic::not_intrinsic) {
+ Function *F = CGM.getIntrinsic(ID, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+ Function *F = CGM.getIntrinsic(Intrinsic::s390_vfidb);
+ Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);
+ Value *M5Value = llvm::ConstantInt::get(getLLVMContext(), M5);
+ return Builder.CreateCall(F, {X, M4Value, M5Value});
+ }
+
+ // Vector intrisincs that output the post-instruction CC value.
+
+#define INTRINSIC_WITH_CC(NAME) \
+ case SystemZ::BI__builtin_##NAME: \
+ return EmitSystemZIntrinsicWithCC(*this, Intrinsic::NAME, E)
+
+ INTRINSIC_WITH_CC(s390_vpkshs);
+ INTRINSIC_WITH_CC(s390_vpksfs);
+ INTRINSIC_WITH_CC(s390_vpksgs);
+
+ INTRINSIC_WITH_CC(s390_vpklshs);
+ INTRINSIC_WITH_CC(s390_vpklsfs);
+ INTRINSIC_WITH_CC(s390_vpklsgs);
+
+ INTRINSIC_WITH_CC(s390_vceqbs);
+ INTRINSIC_WITH_CC(s390_vceqhs);
+ INTRINSIC_WITH_CC(s390_vceqfs);
+ INTRINSIC_WITH_CC(s390_vceqgs);
+
+ INTRINSIC_WITH_CC(s390_vchbs);
+ INTRINSIC_WITH_CC(s390_vchhs);
+ INTRINSIC_WITH_CC(s390_vchfs);
+ INTRINSIC_WITH_CC(s390_vchgs);
+
+ INTRINSIC_WITH_CC(s390_vchlbs);
+ INTRINSIC_WITH_CC(s390_vchlhs);
+ INTRINSIC_WITH_CC(s390_vchlfs);
+ INTRINSIC_WITH_CC(s390_vchlgs);
+
+ INTRINSIC_WITH_CC(s390_vfaebs);
+ INTRINSIC_WITH_CC(s390_vfaehs);
+ INTRINSIC_WITH_CC(s390_vfaefs);
+
+ INTRINSIC_WITH_CC(s390_vfaezbs);
+ INTRINSIC_WITH_CC(s390_vfaezhs);
+ INTRINSIC_WITH_CC(s390_vfaezfs);
+
+ INTRINSIC_WITH_CC(s390_vfeebs);
+ INTRINSIC_WITH_CC(s390_vfeehs);
+ INTRINSIC_WITH_CC(s390_vfeefs);
+
+ INTRINSIC_WITH_CC(s390_vfeezbs);
+ INTRINSIC_WITH_CC(s390_vfeezhs);
+ INTRINSIC_WITH_CC(s390_vfeezfs);
+
+ INTRINSIC_WITH_CC(s390_vfenebs);
+ INTRINSIC_WITH_CC(s390_vfenehs);
+ INTRINSIC_WITH_CC(s390_vfenefs);
+
+ INTRINSIC_WITH_CC(s390_vfenezbs);
+ INTRINSIC_WITH_CC(s390_vfenezhs);
+ INTRINSIC_WITH_CC(s390_vfenezfs);
+
+ INTRINSIC_WITH_CC(s390_vistrbs);
+ INTRINSIC_WITH_CC(s390_vistrhs);
+ INTRINSIC_WITH_CC(s390_vistrfs);
+
+ INTRINSIC_WITH_CC(s390_vstrcbs);
+ INTRINSIC_WITH_CC(s390_vstrchs);
+ INTRINSIC_WITH_CC(s390_vstrcfs);
+
+ INTRINSIC_WITH_CC(s390_vstrczbs);
+ INTRINSIC_WITH_CC(s390_vstrczhs);
+ INTRINSIC_WITH_CC(s390_vstrczfs);
+
+ INTRINSIC_WITH_CC(s390_vfcedbs);
+ INTRINSIC_WITH_CC(s390_vfchdbs);
+ INTRINSIC_WITH_CC(s390_vfchedbs);
+
+ INTRINSIC_WITH_CC(s390_vftcidb);
+
+#undef INTRINSIC_WITH_CC
+
+ default:
+ return nullptr;
+ }
+}
+
+Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case NVPTX::BI__nvvm_atom_add_gen_i:
+ case NVPTX::BI__nvvm_atom_add_gen_l:
+ case NVPTX::BI__nvvm_atom_add_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Add, E);
+
+ case NVPTX::BI__nvvm_atom_sub_gen_i:
+ case NVPTX::BI__nvvm_atom_sub_gen_l:
+ case NVPTX::BI__nvvm_atom_sub_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Sub, E);
+
+ case NVPTX::BI__nvvm_atom_and_gen_i:
+ case NVPTX::BI__nvvm_atom_and_gen_l:
+ case NVPTX::BI__nvvm_atom_and_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::And, E);
+
+ case NVPTX::BI__nvvm_atom_or_gen_i:
+ case NVPTX::BI__nvvm_atom_or_gen_l:
+ case NVPTX::BI__nvvm_atom_or_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Or, E);
+
+ case NVPTX::BI__nvvm_atom_xor_gen_i:
+ case NVPTX::BI__nvvm_atom_xor_gen_l:
+ case NVPTX::BI__nvvm_atom_xor_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xor, E);
+
+ case NVPTX::BI__nvvm_atom_xchg_gen_i:
+ case NVPTX::BI__nvvm_atom_xchg_gen_l:
+ case NVPTX::BI__nvvm_atom_xchg_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xchg, E);
+
+ case NVPTX::BI__nvvm_atom_max_gen_i:
+ case NVPTX::BI__nvvm_atom_max_gen_l:
+ case NVPTX::BI__nvvm_atom_max_gen_ll:
+ case NVPTX::BI__nvvm_atom_max_gen_ui:
+ case NVPTX::BI__nvvm_atom_max_gen_ul:
+ case NVPTX::BI__nvvm_atom_max_gen_ull:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Max, E);
+
+ case NVPTX::BI__nvvm_atom_min_gen_i:
+ case NVPTX::BI__nvvm_atom_min_gen_l:
+ case NVPTX::BI__nvvm_atom_min_gen_ll:
+ case NVPTX::BI__nvvm_atom_min_gen_ui:
+ case NVPTX::BI__nvvm_atom_min_gen_ul:
+ case NVPTX::BI__nvvm_atom_min_gen_ull:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Min, E);
+
+ case NVPTX::BI__nvvm_atom_cas_gen_i:
+ case NVPTX::BI__nvvm_atom_cas_gen_l:
+ case NVPTX::BI__nvvm_atom_cas_gen_ll:
+ return MakeAtomicCmpXchgValue(*this, E, true);
+
+ case NVPTX::BI__nvvm_atom_add_gen_f: {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ Value *Val = EmitScalarExpr(E->getArg(1));
+ // atomicrmw only deals with integer arguments so we need to use
+ // LLVM's nvvm_atomic_load_add_f32 intrinsic for that.
+ Value *FnALAF32 =
+ CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_add_f32, Ptr->getType());
+ return Builder.CreateCall(FnALAF32, {Ptr, Val});
+ }
+
+ default:
+ return nullptr;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
index fb11751..67d0ab7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
@@ -20,7 +20,6 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
-#include <vector>
using namespace clang;
using namespace CodeGen;
@@ -30,29 +29,66 @@ namespace {
class CGNVCUDARuntime : public CGCUDARuntime {
private:
- llvm::Type *IntTy, *SizeTy;
- llvm::PointerType *CharPtrTy, *VoidPtrTy;
+ llvm::Type *IntTy, *SizeTy, *VoidTy;
+ llvm::PointerType *CharPtrTy, *VoidPtrTy, *VoidPtrPtrTy;
+
+ /// Convenience reference to LLVM Context
+ llvm::LLVMContext &Context;
+ /// Convenience reference to the current module
+ llvm::Module &TheModule;
+ /// Keeps track of kernel launch stubs emitted in this module
+ llvm::SmallVector<llvm::Function *, 16> EmittedKernels;
+ /// Keeps track of variables containing handles of GPU binaries. Populated by
+ /// ModuleCtorFunction() and used to create corresponding cleanup calls in
+ /// ModuleDtorFunction()
+ llvm::SmallVector<llvm::GlobalVariable *, 16> GpuBinaryHandles;
llvm::Constant *getSetupArgumentFn() const;
llvm::Constant *getLaunchFn() const;
+ /// Creates a function to register all kernel stubs generated in this module.
+ llvm::Function *makeRegisterKernelsFn();
+
+ /// Helper function that generates a constant string and returns a pointer to
+ /// the start of the string. The result of this function can be used anywhere
+ /// where the C code specifies const char*.
+ llvm::Constant *makeConstantString(const std::string &Str,
+ const std::string &Name = "",
+ unsigned Alignment = 0) {
+ llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0),
+ llvm::ConstantInt::get(SizeTy, 0)};
+ auto *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
+ }
+
+ void emitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args);
+
public:
CGNVCUDARuntime(CodeGenModule &CGM);
- void EmitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args) override;
+ void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) override;
+ /// Creates module constructor function
+ llvm::Function *makeModuleCtorFunction() override;
+ /// Creates module destructor function
+ llvm::Function *makeModuleDtorFunction() override;
};
}
-CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM) : CGCUDARuntime(CGM) {
+CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
+ : CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
+ TheModule(CGM.getModule()) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
IntTy = Types.ConvertType(Ctx.IntTy);
SizeTy = Types.ConvertType(Ctx.getSizeType());
+ VoidTy = llvm::Type::getVoidTy(Context);
CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy));
VoidPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.VoidPtrTy));
+ VoidPtrPtrTy = VoidPtrTy->getPointerTo();
}
llvm::Constant *CGNVCUDARuntime::getSetupArgumentFn() const {
@@ -68,14 +104,17 @@ llvm::Constant *CGNVCUDARuntime::getSetupArgumentFn() const {
llvm::Constant *CGNVCUDARuntime::getLaunchFn() const {
// cudaError_t cudaLaunch(char *)
- std::vector<llvm::Type*> Params;
- Params.push_back(CharPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(IntTy,
- Params, false),
- "cudaLaunch");
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, CharPtrTy, false), "cudaLaunch");
+}
+
+void CGNVCUDARuntime::emitDeviceStub(CodeGenFunction &CGF,
+ FunctionArgList &Args) {
+ EmittedKernels.push_back(CGF.CurFn);
+ emitDeviceStubBody(CGF, Args);
}
-void CGNVCUDARuntime::EmitDeviceStubBody(CodeGenFunction &CGF,
+void CGNVCUDARuntime::emitDeviceStubBody(CodeGenFunction &CGF,
FunctionArgList &Args) {
// Build the argument value list and the argument stack struct type.
SmallVector<llvm::Value *, 16> ArgValues;
@@ -87,8 +126,7 @@ void CGNVCUDARuntime::EmitDeviceStubBody(CodeGenFunction &CGF,
assert(isa<llvm::PointerType>(V->getType()) && "Arg type not PointerType");
ArgTypes.push_back(cast<llvm::PointerType>(V->getType())->getElementType());
}
- llvm::StructType *ArgStackTy = llvm::StructType::get(
- CGF.getLLVMContext(), ArgTypes);
+ llvm::StructType *ArgStackTy = llvm::StructType::get(Context, ArgTypes);
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end");
@@ -120,6 +158,160 @@ void CGNVCUDARuntime::EmitDeviceStubBody(CodeGenFunction &CGF,
CGF.EmitBlock(EndBlock);
}
+/// Creates internal function to register all kernel stubs generated in this
+/// module with the CUDA runtime.
+/// \code
+/// void __cuda_register_kernels(void** GpuBinaryHandle) {
+/// __cudaRegisterFunction(GpuBinaryHandle,Kernel0,...);
+/// ...
+/// __cudaRegisterFunction(GpuBinaryHandle,KernelM,...);
+/// }
+/// \endcode
+llvm::Function *CGNVCUDARuntime::makeRegisterKernelsFn() {
+ llvm::Function *RegisterKernelsFunc = llvm::Function::Create(
+ llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false),
+ llvm::GlobalValue::InternalLinkage, "__cuda_register_kernels", &TheModule);
+ llvm::BasicBlock *EntryBB =
+ llvm::BasicBlock::Create(Context, "entry", RegisterKernelsFunc);
+ CGBuilderTy Builder(Context);
+ Builder.SetInsertPoint(EntryBB);
+
+ // void __cudaRegisterFunction(void **, const char *, char *, const char *,
+ // int, uint3*, uint3*, dim3*, dim3*, int*)
+ std::vector<llvm::Type *> RegisterFuncParams = {
+ VoidPtrPtrTy, CharPtrTy, CharPtrTy, CharPtrTy, IntTy,
+ VoidPtrTy, VoidPtrTy, VoidPtrTy, VoidPtrTy, IntTy->getPointerTo()};
+ llvm::Constant *RegisterFunc = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, RegisterFuncParams, false),
+ "__cudaRegisterFunction");
+
+ // Extract GpuBinaryHandle passed as the first argument passed to
+ // __cuda_register_kernels() and generate __cudaRegisterFunction() call for
+ // each emitted kernel.
+ llvm::Argument &GpuBinaryHandlePtr = *RegisterKernelsFunc->arg_begin();
+ for (llvm::Function *Kernel : EmittedKernels) {
+ llvm::Constant *KernelName = makeConstantString(Kernel->getName());
+ llvm::Constant *NullPtr = llvm::ConstantPointerNull::get(VoidPtrTy);
+ llvm::Value *args[] = {
+ &GpuBinaryHandlePtr, Builder.CreateBitCast(Kernel, VoidPtrTy),
+ KernelName, KernelName, llvm::ConstantInt::get(IntTy, -1), NullPtr,
+ NullPtr, NullPtr, NullPtr,
+ llvm::ConstantPointerNull::get(IntTy->getPointerTo())};
+ Builder.CreateCall(RegisterFunc, args);
+ }
+
+ Builder.CreateRetVoid();
+ return RegisterKernelsFunc;
+}
+
+/// Creates a global constructor function for the module:
+/// \code
+/// void __cuda_module_ctor(void*) {
+/// Handle0 = __cudaRegisterFatBinary(GpuBinaryBlob0);
+/// __cuda_register_kernels(Handle0);
+/// ...
+/// HandleN = __cudaRegisterFatBinary(GpuBinaryBlobN);
+/// __cuda_register_kernels(HandleN);
+/// }
+/// \endcode
+llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
+ // void __cuda_register_kernels(void* handle);
+ llvm::Function *RegisterKernelsFunc = makeRegisterKernelsFn();
+ // void ** __cudaRegisterFatBinary(void *);
+ llvm::Constant *RegisterFatbinFunc = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(VoidPtrPtrTy, VoidPtrTy, false),
+ "__cudaRegisterFatBinary");
+ // struct { int magic, int version, void * gpu_binary, void * dont_care };
+ llvm::StructType *FatbinWrapperTy =
+ llvm::StructType::get(IntTy, IntTy, VoidPtrTy, VoidPtrTy, nullptr);
+
+ llvm::Function *ModuleCtorFunc = llvm::Function::Create(
+ llvm::FunctionType::get(VoidTy, VoidPtrTy, false),
+ llvm::GlobalValue::InternalLinkage, "__cuda_module_ctor", &TheModule);
+ llvm::BasicBlock *CtorEntryBB =
+ llvm::BasicBlock::Create(Context, "entry", ModuleCtorFunc);
+ CGBuilderTy CtorBuilder(Context);
+
+ CtorBuilder.SetInsertPoint(CtorEntryBB);
+
+ // For each GPU binary, register it with the CUDA runtime and store returned
+ // handle in a global variable and save the handle in GpuBinaryHandles vector
+ // to be cleaned up in destructor on exit. Then associate all known kernels
+ // with the GPU binary handle so CUDA runtime can figure out what to call on
+ // the GPU side.
+ for (const std::string &GpuBinaryFileName :
+ CGM.getCodeGenOpts().CudaGpuBinaryFileNames) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> GpuBinaryOrErr =
+ llvm::MemoryBuffer::getFileOrSTDIN(GpuBinaryFileName);
+ if (std::error_code EC = GpuBinaryOrErr.getError()) {
+ CGM.getDiags().Report(diag::err_cannot_open_file) << GpuBinaryFileName
+ << EC.message();
+ continue;
+ }
+
+ // Create initialized wrapper structure that points to the loaded GPU binary
+ llvm::Constant *Values[] = {
+ llvm::ConstantInt::get(IntTy, 0x466243b1), // Fatbin wrapper magic.
+ llvm::ConstantInt::get(IntTy, 1), // Fatbin version.
+ makeConstantString(GpuBinaryOrErr.get()->getBuffer(), "", 16), // Data.
+ llvm::ConstantPointerNull::get(VoidPtrTy)}; // Unused in fatbin v1.
+ llvm::GlobalVariable *FatbinWrapper = new llvm::GlobalVariable(
+ TheModule, FatbinWrapperTy, true, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantStruct::get(FatbinWrapperTy, Values),
+ "__cuda_fatbin_wrapper");
+
+ // GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper);
+ llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall(
+ RegisterFatbinFunc,
+ CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy));
+ llvm::GlobalVariable *GpuBinaryHandle = new llvm::GlobalVariable(
+ TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle");
+ CtorBuilder.CreateStore(RegisterFatbinCall, GpuBinaryHandle, false);
+
+ // Call __cuda_register_kernels(GpuBinaryHandle);
+ CtorBuilder.CreateCall(RegisterKernelsFunc, RegisterFatbinCall);
+
+ // Save GpuBinaryHandle so we can unregister it in destructor.
+ GpuBinaryHandles.push_back(GpuBinaryHandle);
+ }
+
+ CtorBuilder.CreateRetVoid();
+ return ModuleCtorFunc;
+}
+
+/// Creates a global destructor function that unregisters all GPU code blobs
+/// registered by constructor.
+/// \code
+/// void __cuda_module_dtor(void*) {
+/// __cudaUnregisterFatBinary(Handle0);
+/// ...
+/// __cudaUnregisterFatBinary(HandleN);
+/// }
+/// \endcode
+llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() {
+ // void __cudaUnregisterFatBinary(void ** handle);
+ llvm::Constant *UnregisterFatbinFunc = CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false),
+ "__cudaUnregisterFatBinary");
+
+ llvm::Function *ModuleDtorFunc = llvm::Function::Create(
+ llvm::FunctionType::get(VoidTy, VoidPtrTy, false),
+ llvm::GlobalValue::InternalLinkage, "__cuda_module_dtor", &TheModule);
+ llvm::BasicBlock *DtorEntryBB =
+ llvm::BasicBlock::Create(Context, "entry", ModuleDtorFunc);
+ CGBuilderTy DtorBuilder(Context);
+ DtorBuilder.SetInsertPoint(DtorEntryBB);
+
+ for (llvm::GlobalVariable *GpuBinaryHandle : GpuBinaryHandles) {
+ DtorBuilder.CreateCall(UnregisterFatbinFunc,
+ DtorBuilder.CreateLoad(GpuBinaryHandle, false));
+ }
+
+ DtorBuilder.CreateRetVoid();
+ return ModuleDtorFunc;
+}
+
CGCUDARuntime *CodeGen::CreateNVCUDARuntime(CodeGenModule &CGM) {
return new CGNVCUDARuntime(CGM);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h
index 8c162fb..dcacf97 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h
@@ -16,6 +16,10 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
#define LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
+namespace llvm {
+class Function;
+}
+
namespace clang {
class CUDAKernelCallExpr;
@@ -39,10 +43,17 @@ public:
virtual RValue EmitCUDAKernelCallExpr(CodeGenFunction &CGF,
const CUDAKernelCallExpr *E,
ReturnValueSlot ReturnValue);
-
- virtual void EmitDeviceStubBody(CodeGenFunction &CGF,
- FunctionArgList &Args) = 0;
+ /// Emits a kernel launch stub.
+ virtual void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) = 0;
+
+ /// Constructs and returns a module initialization function or nullptr if it's
+ /// not needed. Must be called after all kernels have been emitted.
+ virtual llvm::Function *makeModuleCtorFunction() = 0;
+
+ /// Returns a module cleanup function or nullptr if it's not needed.
+ /// Must be called after ModuleCtorFunction
+ virtual llvm::Function *makeModuleDtorFunction() = 0;
};
/// Creates an instance of a CUDA runtime class.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
index 9f0e67e..7d7ed78 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
@@ -182,8 +182,8 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return true;
// Create the alias with no name.
- auto *Alias = llvm::GlobalAlias::create(AliasType->getElementType(), 0,
- Linkage, "", Aliasee, &getModule());
+ auto *Alias =
+ llvm::GlobalAlias::create(AliasType, Linkage, "", Aliasee, &getModule());
// Switch any previous uses to the alias.
if (Entry) {
@@ -218,6 +218,8 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
}
setFunctionLinkage(GD, Fn);
+ setFunctionDLLStorageClass(GD, Fn);
+
CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
setFunctionDefinitionAttributes(MD, Fn);
SetLLVMFunctionAttributesForDefinition(MD, Fn);
@@ -231,8 +233,7 @@ llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
} else {
- auto *DD = dyn_cast<CXXDestructorDecl>(MD);
- GD = GlobalDecl(DD, toCXXDtorType(Type));
+ GD = GlobalDecl(cast<CXXDestructorDecl>(MD), toCXXDtorType(Type));
}
StringRef Name = getMangledName(GD);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
index d31331d..dc16616 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
@@ -130,10 +130,9 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
return GetBogusMemberPointer(QualType(MPT, 0));
}
-llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
- return GetBogusMemberPointer(
- CGM.getContext().getMemberPointerType(MD->getType(),
- MD->getParent()->getTypeForDecl()));
+llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
+ return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
+ MD->getType(), MD->getParent()->getTypeForDecl()));
}
llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
@@ -302,3 +301,10 @@ CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
return false;
}
+
+llvm::CallInst *
+CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn) {
+ // Just call std::terminate and ignore the violating exception.
+ return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
index cc5c1b2..436b96a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
@@ -22,6 +22,7 @@ namespace llvm {
class Constant;
class Type;
class Value;
+class CallInst;
}
namespace clang {
@@ -171,7 +172,7 @@ public:
virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
/// Create a member pointer for the given method.
- virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+ virtual llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
/// Create a member pointer for the given field.
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
@@ -214,8 +215,18 @@ public:
llvm::Value *Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) = 0;
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0;
+ virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
+ virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
+
+ virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
+
+ virtual llvm::CallInst *
+ emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn);
virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
+ virtual llvm::Constant *
+ getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) = 0;
virtual bool shouldTypeidBeNullChecked(bool IsDeref,
QualType SrcRecordTy) = 0;
@@ -355,7 +366,8 @@ public:
virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) = 0;
+ llvm::Type *Ty,
+ SourceLocation Loc) = 0;
/// Emit the ABI-specific virtual destructor call.
virtual llvm::Value *
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 6403fa9..3e4d7f3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -30,6 +30,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace clang;
using namespace CodeGen;
@@ -51,6 +52,8 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_X86Pascal: return llvm::CallingConv::C;
// TODO: Add support for __vectorcall to LLVM.
case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall;
+ case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC;
+ case CC_SpirKernel: return llvm::CallingConv::SPIR_KERNEL;
}
}
@@ -96,8 +99,7 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
CanQual<FunctionProtoType> FTP) {
RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
// FIXME: Kill copy.
- for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
- prefix.push_back(FTP->getParamType(i));
+ prefix.append(FTP->param_type_begin(), FTP->param_type_end());
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod,
/*chainCall=*/false, prefix,
@@ -133,9 +135,6 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
if (PcsAttr *PCS = D->getAttr<PcsAttr>())
return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP);
- if (D->hasAttr<PnaclCallAttr>())
- return CC_PnaclCall;
-
if (D->hasAttr<IntelOclBiccAttr>())
return CC_IntelOclBicc;
@@ -208,8 +207,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
// Add the formal parameters.
- for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
- argTypes.push_back(FTP->getParamType(i));
+ argTypes.append(FTP->param_type_begin(), FTP->param_type_end());
TheCXXABI.buildStructorSignature(MD, Type, argTypes);
@@ -349,6 +347,26 @@ CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) {
FTP->getExtInfo(), RequiredArgs(1));
}
+const CGFunctionInfo &
+CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
+ CXXCtorType CT) {
+ assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure);
+
+ CanQual<FunctionProtoType> FTP = GetFormalType(CD);
+ SmallVector<CanQualType, 2> ArgTys;
+ const CXXRecordDecl *RD = CD->getParent();
+ ArgTys.push_back(GetThisType(Context, RD));
+ if (CT == Ctor_CopyingClosure)
+ ArgTys.push_back(*FTP->param_type_begin());
+ if (RD->getNumVBases() > 0)
+ ArgTys.push_back(Context.IntTy);
+ CallingConv CC = Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+ return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true,
+ /*chainCall=*/false, ArgTys,
+ FunctionType::ExtInfo(CC), RequiredArgs::All);
+}
+
/// Arrange a call as unto a free function, except possibly with an
/// additional number of formal parameters considered required.
static const CGFunctionInfo &
@@ -716,7 +734,8 @@ void CodeGenFunction::ExpandTypeFromArgs(
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, i);
+ llvm::Value *EltAddr =
+ Builder.CreateConstGEP2_32(nullptr, LV.getAddress(), 0, i);
LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy);
ExpandTypeFromArgs(CAExp->EltTy, LV, AI);
}
@@ -738,10 +757,12 @@ void CodeGenFunction::ExpandTypeFromArgs(
ExpandTypeFromArgs(FD->getType(), SubLV, AI);
}
} else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) {
- llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
+ llvm::Value *RealAddr =
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), 0, "real");
EmitStoreThroughLValue(RValue::get(*AI++),
MakeAddrLValue(RealAddr, CExp->EltTy));
- llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
+ llvm::Value *ImagAddr =
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), 1, "imag");
EmitStoreThroughLValue(RValue::get(*AI++),
MakeAddrLValue(ImagAddr, CExp->EltTy));
} else {
@@ -757,7 +778,7 @@ void CodeGenFunction::ExpandTypeToArgs(
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
llvm::Value *Addr = RV.getAggregateAddr();
for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, i);
+ llvm::Value *EltAddr = Builder.CreateConstGEP2_32(nullptr, Addr, 0, i);
RValue EltRV =
convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation());
ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
@@ -825,7 +846,7 @@ EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr,
return SrcPtr;
// GEP into the first element.
- SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcPtr, 0, 0, "coerce.dive");
+ SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcSTy, SrcPtr, 0, 0, "coerce.dive");
// If the first element is a struct, recurse.
llvm::Type *SrcTy =
@@ -891,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);
@@ -919,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);
}
@@ -933,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
@@ -958,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(DestPtr, 0, 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;
}
@@ -1006,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;
}
@@ -1016,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.
@@ -1028,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);
}
}
@@ -1403,7 +1429,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute(llvm::Attribute::ReadOnly);
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
- if (TargetDecl->hasAttr<MallocAttr>())
+ if (TargetDecl->hasAttr<RestrictAttr>())
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
if (TargetDecl->hasAttr<ReturnsNonNullAttr>())
RetAttrs.addAttribute(llvm::Attribute::NonNull);
@@ -1431,6 +1457,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// Attributes that should go on the call site only.
if (!CodeGenOpts.SimplifyLibCalls)
FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
+ if (!CodeGenOpts.TrapFuncName.empty())
+ FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
} else {
// Attributes that should go on the function, but not the call site.
if (!CodeGenOpts.DisableFPElim) {
@@ -1443,6 +1471,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
}
+ FuncAttrs.addAttribute("disable-tail-calls",
+ llvm::toStringRef(CodeGenOpts.DisableTailCalls));
FuncAttrs.addAttribute("less-precise-fpmad",
llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
FuncAttrs.addAttribute("no-infs-fp-math",
@@ -1458,6 +1488,76 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (!CodeGenOpts.StackRealignment)
FuncAttrs.addAttribute("no-realign-stack");
+
+ // Add target-cpu and target-features attributes to functions. If
+ // we have a decl for the function and it has a target attribute then
+ // parse that and add it to the feature set.
+ StringRef TargetCPU = getTarget().getTargetOpts().CPU;
+
+ // TODO: Features gets us the features on the command line including
+ // feature dependencies. For canonicalization purposes we might want to
+ // avoid putting features in the target-features set if we know it'll be
+ // one of the default features in the backend, e.g. corei7-avx and +avx or
+ // figure out non-explicit dependencies.
+ // Canonicalize the existing features in a new feature map.
+ // TODO: Migrate the existing backends to keep the map around rather than
+ // the vector.
+ llvm::StringMap<bool> FeatureMap;
+ for (auto F : getTarget().getTargetOpts().Features) {
+ const char *Name = F.c_str();
+ bool Enabled = Name[0] == '+';
+ getTarget().setFeatureEnabled(FeatureMap, Name + 1, Enabled);
+ }
+
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
+ if (FD) {
+ if (const auto *TD = FD->getAttr<TargetAttr>()) {
+ StringRef FeaturesStr = TD->getFeatures();
+ SmallVector<StringRef, 1> AttrFeatures;
+ FeaturesStr.split(AttrFeatures, ",");
+
+ // 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.trim();
+ else if (Feature.startswith("tune="))
+ // We don't support cpu tuning this way currently.
+ ;
+ else if (Feature.startswith("fpmath="))
+ // TODO: Support the fpmath option this way. It will require checking
+ // overall feature validity for the function with the rest of the
+ // attributes on the function.
+ ;
+ else if (Feature.startswith("mno-"))
+ getTarget().setFeatureEnabled(FeatureMap, Feature.split("-").second,
+ false);
+ else
+ getTarget().setFeatureEnabled(FeatureMap, Feature, true);
+ }
+ }
+ }
+
+ // Produce the canonical string for this set of features.
+ std::vector<std::string> Features;
+ for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
+ ie = FeatureMap.end();
+ it != ie; ++it)
+ Features.push_back((it->second ? "+" : "-") + it->first().str());
+
+ // Now add the target-cpu and target-features to the function.
+ if (TargetCPU != "")
+ FuncAttrs.addAttribute("target-cpu", TargetCPU);
+ if (!Features.empty()) {
+ std::sort(Features.begin(), Features.end());
+ FuncAttrs.addAttribute("target-features",
+ llvm::join(Features.begin(), Features.end(), ","));
+ }
}
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
@@ -1546,8 +1646,12 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
case ABIArgInfo::Extend:
if (ParamType->isSignedIntegerOrEnumerationType())
Attrs.addAttribute(llvm::Attribute::SExt);
- else if (ParamType->isUnsignedIntegerOrEnumerationType())
- Attrs.addAttribute(llvm::Attribute::ZExt);
+ else if (ParamType->isUnsignedIntegerOrEnumerationType()) {
+ if (getTypes().getABIInfo().shouldSignExtUnsignedType(ParamType))
+ Attrs.addAttribute(llvm::Attribute::SExt);
+ else
+ Attrs.addAttribute(llvm::Attribute::ZExt);
+ }
// FALL THROUGH
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
@@ -1734,8 +1838,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
switch (ArgI.getKind()) {
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
- llvm::Value *V = Builder.CreateStructGEP(
- ArgStruct, ArgI.getInAllocaFieldIndex(), Arg->getName());
+ llvm::Value *V =
+ Builder.CreateStructGEP(FI.getArgStruct(), ArgStruct,
+ ArgI.getInAllocaFieldIndex(), Arg->getName());
ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
break;
}
@@ -1770,8 +1875,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
} else {
// Load scalar value from indirect argument.
- CharUnits Alignment = getContext().getTypeAlignInChars(Ty);
- V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty,
+ V = EmitLoadOfScalar(V, false, ArgI.getIndirectAlign(), Ty,
Arg->getLocStart());
if (isPromoted)
@@ -1897,13 +2001,15 @@ 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()) {
Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy());
- Ptr = Builder.CreateConstGEP1_32(Ptr, Offs);
+ 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
@@ -1923,7 +2029,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
auto AI = FnArgs[FirstIRArg + i];
AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(Ptr, 0, i);
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, Ptr, 0, i);
Builder.CreateStore(AI, EltPtr);
}
} else {
@@ -1936,7 +2042,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
auto AI = FnArgs[FirstIRArg + i];
AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(TempV, 0, i);
+ llvm::Value *EltPtr =
+ Builder.CreateConstGEP2_32(ArgI.getCoerceToType(), TempV, 0, i);
Builder.CreateStore(AI, EltPtr);
}
@@ -1947,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);
}
@@ -2173,7 +2280,28 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
if (!CGF.ReturnValue->hasOneUse()) {
llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
if (IP->empty()) return nullptr;
- llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(&IP->back());
+ llvm::Instruction *I = &IP->back();
+
+ // Skip lifetime markers
+ for (llvm::BasicBlock::reverse_iterator II = IP->rbegin(),
+ IE = IP->rend();
+ II != IE; ++II) {
+ if (llvm::IntrinsicInst *Intrinsic =
+ dyn_cast<llvm::IntrinsicInst>(&*II)) {
+ if (Intrinsic->getIntrinsicID() == llvm::Intrinsic::lifetime_end) {
+ const llvm::Value *CastAddr = Intrinsic->getArgOperand(1);
+ ++II;
+ if (II == IE)
+ break;
+ if (isa<llvm::BitCastInst>(&*II) && (CastAddr == &*II))
+ continue;
+ }
+ }
+ I = &*II;
+ break;
+ }
+
+ llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(I);
if (!store) return nullptr;
if (store->getPointerOperand() != CGF.ReturnValue) return nullptr;
assert(!store->isAtomic() && !store->isVolatile()); // see below
@@ -2231,8 +2359,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
llvm::Value *ArgStruct = EI;
- llvm::Value *SRet =
- Builder.CreateStructGEP(ArgStruct, RetAI.getInAllocaFieldIndex());
+ llvm::Value *SRet = Builder.CreateStructGEP(
+ nullptr, ArgStruct, RetAI.getInAllocaFieldIndex());
RV = Builder.CreateLoad(SRet, "sret");
}
break;
@@ -2271,7 +2399,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
// If there is a dominating store to ReturnValue, we can elide
// the load, zap the store, and usually zap the alloca.
- if (llvm::StoreInst *SI = findDominatingStoreToReturnValue(*this)) {
+ if (llvm::StoreInst *SI =
+ findDominatingStoreToReturnValue(*this)) {
// Reuse the debug location from the store unless there is
// cleanup code to be emitted between the store and return
// instruction.
@@ -2293,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(V, Offs);
+ 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
@@ -2342,8 +2473,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
Ret = Builder.CreateRetVoid();
}
- if (!RetDbgLoc.isUnknown())
- Ret->setDebugLoc(RetDbgLoc);
+ if (RetDbgLoc)
+ Ret->setDebugLoc(std::move(RetDbgLoc));
}
static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
@@ -2501,7 +2632,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
LValue srcLV;
// Make an optimistic effort to emit the address as an l-value.
- // This can fail if the the argument expression is more complicated.
+ // This can fail if the argument expression is more complicated.
if (const Expr *lvExpr = maybeGetUnaryAddrOfOperand(CRE->getSubExpr())) {
srcLV = CGF.EmitLValue(lvExpr);
@@ -2626,7 +2757,7 @@ void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
// Save the stack.
llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave);
- StackBase = CGF.Builder.CreateCall(F, "inalloca.save");
+ StackBase = CGF.Builder.CreateCall(F, {}, "inalloca.save");
// Control gets really tied up in landing pads, so we have to spill the
// stacksave to an alloca to avoid violating SSA form.
@@ -2649,27 +2780,28 @@ void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const {
}
}
-static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV,
- QualType ArgType, SourceLocation ArgLoc,
- const FunctionDecl *FD, unsigned ParmNum) {
- if (!CGF.SanOpts.has(SanitizerKind::NonnullAttribute) || !FD)
+void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
+ SourceLocation ArgLoc,
+ const FunctionDecl *FD,
+ unsigned ParmNum) {
+ if (!SanOpts.has(SanitizerKind::NonnullAttribute) || !FD)
return;
auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr;
unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum;
auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo);
if (!NNAttr)
return;
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SanitizerScope SanScope(this);
assert(RV.isScalar());
llvm::Value *V = RV.getScalarVal();
llvm::Value *Cond =
- CGF.Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType()));
+ Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType()));
llvm::Constant *StaticData[] = {
- CGF.EmitCheckSourceLocation(ArgLoc),
- CGF.EmitCheckSourceLocation(NNAttr->getLocation()),
- llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
+ EmitCheckSourceLocation(ArgLoc),
+ EmitCheckSourceLocation(NNAttr->getLocation()),
+ llvm::ConstantInt::get(Int32Ty, ArgNo + 1),
};
- CGF.EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute),
+ EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute),
"nonnull_arg", StaticData, None);
}
@@ -2678,12 +2810,7 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
const FunctionDecl *CalleeDecl,
- unsigned ParamsToSkip,
- bool ForceColumnInfo) {
- CGDebugInfo *DI = getDebugInfo();
- SourceLocation CallLoc;
- if (DI) CallLoc = DI->getLocation();
-
+ unsigned ParamsToSkip) {
// We *have* to evaluate arguments from right to left in the MS C++ ABI,
// because arguments are destroyed left to right in the callee.
if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
@@ -2702,10 +2829,8 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args,
for (int I = ArgTypes.size() - 1; I >= 0; --I) {
CallExpr::const_arg_iterator Arg = ArgBeg + I;
EmitCallArg(Args, *Arg, ArgTypes[I]);
- emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
+ EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
CalleeDecl, ParamsToSkip + I);
- // Restore the debug location.
- if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
}
// Un-reverse the arguments we just evaluated so they match up with the LLVM
@@ -2718,10 +2843,8 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args,
CallExpr::const_arg_iterator Arg = ArgBeg + I;
assert(Arg != ArgEnd);
EmitCallArg(Args, *Arg, ArgTypes[I]);
- emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
+ EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
CalleeDecl, ParamsToSkip + I);
- // Restore the debug location.
- if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
}
}
@@ -2744,8 +2867,22 @@ struct DestroyUnpassedArg : EHScopeStack::Cleanup {
}
+struct DisableDebugLocationUpdates {
+ CodeGenFunction &CGF;
+ bool disabledDebugInfo;
+ DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) {
+ if ((disabledDebugInfo = isa<CXXDefaultArgExpr>(E) && CGF.getDebugInfo()))
+ CGF.disableDebugInfo();
+ }
+ ~DisableDebugLocationUpdates() {
+ if (disabledDebugInfo)
+ CGF.enableDebugInfo();
+ }
+};
+
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) {
+ DisableDebugLocationUpdates Dis(*this, E);
if (const ObjCIndirectCopyRestoreExpr *CRE
= dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
assert(getLangOpts().ObjCAutoRefCount);
@@ -2900,7 +3037,6 @@ void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
call->setCallingConv(getRuntimeCC());
Builder.CreateUnreachable();
}
- PGO.setCurrentRegionUnreachable();
}
/// Emits a call or invoke instruction to the given nullary runtime
@@ -2949,7 +3085,7 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
if (CGM.getLangOpts().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(Inst);
- return Inst;
+ return llvm::CallSite(Inst);
}
/// \brief Store a non-aggregate value to an address to initialize it. For
@@ -2986,7 +3122,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here!
- llvm::Value *ArgMemory = nullptr;
+ llvm::AllocaInst *ArgMemory = nullptr;
if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
llvm::Instruction *IP = CallArgs.getStackBase();
llvm::AllocaInst *AI;
@@ -3007,15 +3143,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
llvm::Value *SRetPtr = nullptr;
+ size_t UnusedReturnSize = 0;
if (RetAI.isIndirect() || RetAI.isInAlloca()) {
SRetPtr = ReturnValue.getValue();
- if (!SRetPtr)
+ if (!SRetPtr) {
SRetPtr = CreateMemTemp(RetTy);
+ if (HaveInsertPoint() && ReturnValue.isUnused()) {
+ uint64_t size =
+ CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
+ if (EmitLifetimeStart(size, SRetPtr))
+ UnusedReturnSize = size;
+ }
+ }
if (IRFunctionArgs.hasSRetArg()) {
IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr;
} else {
llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex());
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ RetAI.getInAllocaFieldIndex());
Builder.CreateStore(SRetPtr, Addr);
}
}
@@ -3049,14 +3194,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
cast<llvm::Instruction>(RV.getAggregateAddr());
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
- llvm::Value *Addr = Builder.CreateStructGEP(
- ArgMemory, ArgInfo.getInAllocaFieldIndex());
+ llvm::Value *Addr =
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
deferPlaceholderReplacement(Placeholder, Addr);
} else {
// Store the RValue into the argument struct.
llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex());
+ Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
+ ArgInfo.getInAllocaFieldIndex());
unsigned AS = Addr->getType()->getPointerAddressSpace();
llvm::Type *MemType = ConvertTypeForMem(I->Ty)->getPointerTo(AS);
// There are some cases where a trivial bitcast is not avoidable. The
@@ -3100,8 +3247,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
: 0);
if ((!ArgInfo.getIndirectByVal() && I->NeedsCopy) ||
(ArgInfo.getIndirectByVal() && TypeAlign.getQuantity() < Align &&
- llvm::getOrEnforceKnownAlignment(Addr, Align, TD) < Align) ||
- (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
+ llvm::getOrEnforceKnownAlignment(Addr, Align, *TD) < Align) ||
+ (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
// Create an aligned temporary, and copy to it.
llvm::AllocaInst *AI = CreateMemTemp(I->Ty);
if (Align > AI->getAlignment())
@@ -3148,20 +3295,25 @@ 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()) {
SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy());
- SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs);
+ 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
@@ -3190,7 +3342,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(NumIRArgs == STy->getNumElements());
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i);
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, SrcPtr, 0, i);
llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);
// We don't know what we're loading from.
LI->setAlignment(1);
@@ -3200,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;
@@ -3300,7 +3453,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::BasicBlock *InvokeDest = nullptr;
if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind))
+ llvm::Attribute::NoUnwind) ||
+ currentFunctionUsesSEHTry())
InvokeDest = getInvokeDest();
llvm::CallSite CS;
@@ -3320,6 +3474,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
+ // Disable inlining inside SEH __try blocks.
+ if (isSEHTryScope())
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoInline);
+
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
@@ -3332,6 +3492,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRgen to discard
// unreachable code.
if (CS.doesNotReturn()) {
+ if (UnusedReturnSize)
+ EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
+ SRetPtr);
+
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
@@ -3360,8 +3524,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
RValue Ret = [&] {
switch (RetAI.getKind()) {
case ABIArgInfo::InAlloca:
- case ABIArgInfo::Indirect:
- return convertTempToRValue(SRetPtr, RetTy, SourceLocation());
+ case ABIArgInfo::Indirect: {
+ RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
+ if (UnusedReturnSize)
+ EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
+ SRetPtr);
+ return ret;
+ }
case ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to
@@ -3381,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: {
@@ -3403,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");
@@ -3411,13 +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(StorePtr, Offs);
+ 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/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
index b228733..7a4708e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
@@ -155,17 +155,25 @@ namespace CodeGen {
/// ReturnValueSlot - Contains the address where the return value of a
/// function can be stored, and whether the address is volatile or not.
class ReturnValueSlot {
- llvm::PointerIntPair<llvm::Value *, 1, bool> Value;
+ llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value;
+
+ // Return value slot flags
+ enum Flags {
+ IS_VOLATILE = 0x1,
+ IS_UNUSED = 0x2,
+ };
public:
ReturnValueSlot() {}
- ReturnValueSlot(llvm::Value *Value, bool IsVolatile)
- : Value(Value, IsVolatile) {}
+ ReturnValueSlot(llvm::Value *Value, bool IsVolatile, bool IsUnused = false)
+ : Value(Value,
+ (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)) {}
bool isNull() const { return !getValue(); }
-
- bool isVolatile() const { return Value.getInt(); }
+
+ bool isVolatile() const { return Value.getInt() & IS_VOLATILE; }
llvm::Value *getValue() const { return Value.getPointer(); }
+ bool isUnused() const { return Value.getInt() & IS_UNUSED; }
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index d72eda9..c49f182 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -24,35 +24,35 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/IR/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
-static CharUnits
-ComputeNonVirtualBaseClassOffset(ASTContext &Context,
- const CXXRecordDecl *DerivedClass,
- CastExpr::path_const_iterator Start,
- CastExpr::path_const_iterator End) {
+CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
+ const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start,
+ CastExpr::path_const_iterator End) {
CharUnits Offset = CharUnits::Zero();
-
+
+ const ASTContext &Context = getContext();
const CXXRecordDecl *RD = DerivedClass;
-
+
for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
const CXXBaseSpecifier *Base = *I;
assert(!Base->isVirtual() && "Should not see virtual bases here!");
// Get the layout.
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- const CXXRecordDecl *BaseDecl =
+
+ const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
+
// Add the offset.
Offset += Layout.getBaseClassOffset(BaseDecl);
-
+
RD = BaseDecl;
}
-
+
return Offset;
}
@@ -62,15 +62,14 @@ CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
CastExpr::path_const_iterator PathEnd) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
- CharUnits Offset =
- ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
- PathBegin, PathEnd);
+ CharUnits Offset =
+ computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd);
if (Offset.isZero())
return nullptr;
- llvm::Type *PtrDiffTy =
+ llvm::Type *PtrDiffTy =
Types.ConvertType(getContext().getPointerDiffType());
-
+
return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity());
}
@@ -127,7 +126,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ptr,
} else {
baseOffset = virtualOffset;
}
-
+
// Apply the base offset.
ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy);
ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr");
@@ -149,7 +148,7 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
// *start* with a step down to the correct virtual base subobject,
// and hence will not require any further steps.
if ((*Start)->isVirtual()) {
- VBase =
+ VBase =
cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl());
++Start;
}
@@ -157,9 +156,8 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
// Compute the static offset of the ultimate destination within its
// allocating subobject (the virtual base, if there is one, or else
// the "complete" object that we see).
- CharUnits NonVirtualOffset =
- ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
- Start, PathEnd);
+ CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset(
+ VBase ? VBase : Derived, Start, PathEnd);
// If there's a virtual step, we can sometimes "devirtualize" it.
// For now, that's limited to when the derived type is final.
@@ -172,7 +170,7 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
}
// Get the base pointer type.
- llvm::Type *BasePtrTy =
+ llvm::Type *BasePtrTy =
ConvertType((PathEnd[-1])->getType())->getPointerTo();
QualType DerivedTy = getContext().getRecordType(Derived);
@@ -197,7 +195,7 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
origBB = Builder.GetInsertBlock();
llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
endBB = createBasicBlock("cast.end");
-
+
llvm::Value *isNull = Builder.CreateIsNull(Value);
Builder.CreateCondBr(isNull, endBB, notNullBB);
EmitBlock(notNullBB);
@@ -216,10 +214,10 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
}
// Apply both offsets.
- Value = ApplyNonVirtualAndVirtualOffset(*this, Value,
+ Value = ApplyNonVirtualAndVirtualOffset(*this, Value,
NonVirtualOffset,
VirtualOffset);
-
+
// Cast to the destination type.
Value = Builder.CreateBitCast(Value, BasePtrTy);
@@ -228,13 +226,13 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();
Builder.CreateBr(endBB);
EmitBlock(endBB);
-
+
llvm::PHINode *PHI = Builder.CreatePHI(BasePtrTy, 2, "cast.result");
PHI->addIncoming(Value, notNullBB);
PHI->addIncoming(llvm::Constant::getNullValue(BasePtrTy), origBB);
Value = PHI;
}
-
+
return Value;
}
@@ -252,7 +250,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
llvm::Value *NonVirtualOffset =
CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
-
+
if (!NonVirtualOffset) {
// No offset, we can just cast back.
return Builder.CreateBitCast(Value, DerivedPtrTy);
@@ -266,12 +264,12 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
CastNull = createBasicBlock("cast.null");
CastNotNull = createBasicBlock("cast.notnull");
CastEnd = createBasicBlock("cast.end");
-
+
llvm::Value *IsNull = Builder.CreateIsNull(Value);
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
EmitBlock(CastNotNull);
}
-
+
// Apply the offset.
Value = Builder.CreateBitCast(Value, Int8PtrTy);
Value = Builder.CreateGEP(Value, Builder.CreateNeg(NonVirtualOffset),
@@ -285,14 +283,14 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
EmitBlock(CastNull);
Builder.CreateBr(CastEnd);
EmitBlock(CastEnd);
-
+
llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
PHI->addIncoming(Value, CastNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
+ PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
CastNull);
Value = PHI;
}
-
+
return Value;
}
@@ -303,7 +301,7 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
// This constructor/destructor does not need a VTT parameter.
return nullptr;
}
-
+
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
@@ -323,15 +321,15 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
SubVTTIndex = 0;
} else {
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
- CharUnits BaseOffset = ForVirtualBase ?
- Layout.getVBaseClassOffset(Base) :
+ CharUnits BaseOffset = ForVirtualBase ?
+ Layout.getVBaseClassOffset(Base) :
Layout.getBaseClassOffset(Base);
- SubVTTIndex =
+ SubVTTIndex =
CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
}
-
+
if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
// A VTT parameter was passed to the constructor, use it.
VTT = LoadCXXVTT();
@@ -358,7 +356,7 @@ namespace {
cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
const CXXDestructorDecl *D = BaseClass->getDestructor();
- llvm::Value *Addr =
+ llvm::Value *Addr =
CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(),
DerivedClass, BaseClass,
BaseIsVirtual);
@@ -369,29 +367,29 @@ namespace {
/// A visitor which checks whether an initializer uses 'this' in a
/// way which requires the vtable to be properly set.
- struct DynamicThisUseChecker : EvaluatedExprVisitor<DynamicThisUseChecker> {
- typedef EvaluatedExprVisitor<DynamicThisUseChecker> super;
+ struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
+ typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
bool UsesThis;
- DynamicThisUseChecker(ASTContext &C) : super(C), UsesThis(false) {}
+ DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
// Black-list all explicit and implicit references to 'this'.
//
// Do we need to worry about external references to 'this' derived
// from arbitrary code? If so, then anything which runs arbitrary
// external code might potentially access the vtable.
- void VisitCXXThisExpr(CXXThisExpr *E) { UsesThis = true; }
+ void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
};
}
static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
DynamicThisUseChecker Checker(C);
- Checker.Visit(const_cast<Expr*>(Init));
+ Checker.Visit(Init);
return Checker.UsesThis;
}
-static void EmitBaseInitializer(CodeGenFunction &CGF,
+static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *BaseInit,
CXXCtorType CtorType) {
@@ -399,7 +397,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
"Must have base initializer!");
llvm::Value *ThisPtr = CGF.LoadCXXThis();
-
+
const Type *BaseType = BaseInit->getBaseClass();
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
@@ -418,7 +416,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
// We can pretend to be a complete class because it only matters for
// virtual bases, and we only do virtual bases for complete ctors.
- llvm::Value *V =
+ llvm::Value *V =
CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
BaseClassDecl,
isBaseVirtual);
@@ -430,8 +428,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
AggValueSlot::IsNotAliased);
CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
-
- if (CGF.CGM.getLangOpts().Exceptions &&
+
+ if (CGF.CGM.getLangOpts().Exceptions &&
!BaseClassDecl->hasTrivialDestructor())
CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl,
isBaseVirtual);
@@ -490,17 +488,17 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
llvm::Value *IndexVar
= CGF.GetAddrOfLocalVar(ArrayIndexes[Index]);
assert(IndexVar && "Array index variable not loaded");
-
+
// Initialize this index variable to zero.
llvm::Value* Zero
= llvm::Constant::getNullValue(
CGF.ConvertType(CGF.getContext().getSizeType()));
CGF.Builder.CreateStore(Zero, IndexVar);
-
+
// Start the loop with a block that tests the condition.
llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond");
llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end");
-
+
CGF.EmitBlock(CondBlock);
llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body");
@@ -512,7 +510,7 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
llvm::ConstantInt::get(Counter->getType(), NumElements);
llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr,
"isless");
-
+
// If the condition is true, execute the body.
CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor);
@@ -539,6 +537,37 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
CGF.EmitBlock(AfterFor, true);
}
+static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {
+ auto *CD = dyn_cast<CXXConstructorDecl>(D);
+ if (!(CD && CD->isCopyOrMoveConstructor()) &&
+ !D->isCopyAssignmentOperator() && !D->isMoveAssignmentOperator())
+ return false;
+
+ // We can emit a memcpy for a trivial copy or move constructor/assignment.
+ if (D->isTrivial() && !D->getParent()->mayInsertExtraPadding())
+ return true;
+
+ // We *must* emit a memcpy for a defaulted union copy or move op.
+ if (D->getParent()->isUnion() && D->isDefaulted())
+ return true;
+
+ 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,
@@ -548,7 +577,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
assert(MemberInit->isAnyMemberInitializer() &&
"Must have member initializer!");
assert(MemberInit->getInit() && "Must have initializer!");
-
+
// non-static data member initializers.
FieldDecl *Field = MemberInit->getAnyMember();
QualType FieldType = Field->getType();
@@ -557,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
@@ -580,17 +600,22 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
if (BaseElementTy.isPODType(CGF.getContext()) ||
- (CE && CE->getConstructor()->isTrivial())) {
+ (CE && isMemcpyEquivalentSpecialMember(CE->getConstructor()))) {
unsigned SrcArgIndex =
CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args);
llvm::Value *SrcPtr
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
-
+
// 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;
}
}
@@ -621,28 +646,28 @@ void CodeGenFunction::EmitInitializerForField(
llvm::Value *ArrayIndexVar = nullptr;
if (ArrayIndexes.size()) {
llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
-
+
// The LHS is a pointer to the first object we'll be constructing, as
// a flat array.
QualType BaseElementTy = getContext().getBaseElementType(FieldType);
llvm::Type *BasePtr = ConvertType(BaseElementTy);
BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(),
+ llvm::Value *BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(),
BasePtr);
LHS = MakeAddrLValue(BaseAddrPtr, BaseElementTy);
-
+
// Create an array index that will be used to walk over all of the
// objects we're constructing.
ArrayIndexVar = CreateTempAlloca(SizeTy, "object.index");
llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
Builder.CreateStore(Zero, ArrayIndexVar);
-
-
+
+
// Emit the block variables for the array indices, if any.
for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I)
EmitAutoVarDecl(*ArrayIndexes[I]);
}
-
+
EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType,
ArrayIndexes, 0);
}
@@ -762,9 +787,9 @@ void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {
if (PoisonSize < AsanAlignment || !SSV[i].Size ||
(NextField % AsanAlignment) != 0)
continue;
- Builder.CreateCall2(
- F, Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)),
- Builder.getIntN(PtrSize, PoisonSize));
+ Builder.CreateCall(
+ F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)),
+ Builder.getIntN(PtrSize, PoisonSize)});
}
}
@@ -796,8 +821,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
if (IsTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
- RegionCounter Cnt = getPGORegionCounter(Body);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(Body);
RunCleanupsScope RunCleanups(*this);
@@ -850,7 +874,7 @@ namespace {
public:
FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
const VarDecl *SrcRec)
- : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
+ : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),
LastFieldOffset(0), LastAddedFieldIndex(0) {}
@@ -876,7 +900,7 @@ namespace {
unsigned LastFieldSize =
LastField->isBitField() ?
LastField->getBitWidthValue(CGF.getContext()) :
- CGF.getContext().getTypeSize(LastField->getType());
+ CGF.getContext().getTypeSize(LastField->getType());
uint64_t MemcpySizeBits =
LastFieldOffset + LastFieldSize - FirstByteOffset +
CGF.getContext().getCharWidth() - 1;
@@ -892,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();
@@ -927,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);
@@ -1021,8 +1034,8 @@ namespace {
QualType FieldType = Field->getType();
CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
- // Bail out on non-POD, not-trivially-constructable members.
- if (!(CE && CE->getConstructor()->isTrivial()) &&
+ // Bail out on non-memcpyable, not-trivially-copyable members.
+ if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) &&
!(FieldType.isTriviallyCopyableType(CGF.getContext()) ||
FieldType->isReferenceType()))
return false;
@@ -1064,6 +1077,7 @@ namespace {
CopyingValueRepresentation CVR(CGF);
EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
AggregatedInits[0], ConstructorDecl, Args);
+ AggregatedInits.clear();
}
reset();
return;
@@ -1080,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);
}
}
@@ -1127,9 +1145,7 @@ namespace {
return Field;
} else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
- if (!(MD && (MD->isCopyAssignmentOperator() ||
- MD->isMoveAssignmentOperator()) &&
- MD->isTrivial()))
+ if (!(MD && isMemcpyEquivalentSpecialMember(MD)))
return nullptr;
MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
if (!IOA)
@@ -1189,7 +1205,7 @@ namespace {
if (F) {
addMemcpyableField(F);
AggregatedStmts.push_back(S);
- } else {
+ } else {
emitAggregatedStmts();
CGF.EmitStmt(S);
}
@@ -1274,7 +1290,7 @@ static bool
FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
static bool
-HasTrivialDestructorBody(ASTContext &Context,
+HasTrivialDestructorBody(ASTContext &Context,
const CXXRecordDecl *BaseClassDecl,
const CXXRecordDecl *MostDerivedClassDecl)
{
@@ -1309,7 +1325,7 @@ HasTrivialDestructorBody(ASTContext &Context,
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
if (!HasTrivialDestructorBody(Context, VirtualBase,
MostDerivedClassDecl))
- return false;
+ return false;
}
}
@@ -1325,8 +1341,13 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
if (!RT)
return true;
-
+
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+ // The destructor for an implicit anonymous union member is never invoked.
+ if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+ return false;
+
return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
}
@@ -1346,11 +1367,34 @@ 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());
CXXDtorType DtorType = CurGD.getDtorType();
+ Stmt *Body = Dtor->getBody();
+ if (Body)
+ incrementProfileCounter(Body);
+
// The call to operator delete in a deleting destructor happens
// outside of the function-try-block, which means it's always
// possible to delegate the destructor body to the complete
@@ -1363,8 +1407,6 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
return;
}
- Stmt *Body = Dtor->getBody();
-
// If the body is a function-try-block, enter the try before
// anything else.
bool isTryBody = (Body && isa<CXXTryStmt>(Body));
@@ -1374,11 +1416,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Enter the epilogue cleanups.
RunCleanupsScope DtorEpilogue(*this);
-
+
// If this is the complete variant, just invoke the base variant;
// the epilogue will destruct the virtual bases. But we can't do
// this optimization if the body is a function-try-block, because
- // we'd introduce *two* handler blocks. In the Microsoft ABI, we
+ // we'd introduce *two* handler blocks. In the Microsoft ABI, we
// always delegate because we might not have a definition in this TU.
switch (DtorType) {
case Dtor_Comdat:
@@ -1399,13 +1441,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
break;
}
// Fallthrough: act like we're in the base variant.
-
+
case Dtor_Base:
assert(Body);
- RegionCounter Cnt = getPGORegionCounter(Body);
- Cnt.beginRegion(Builder);
-
// Enter the cleanup scopes for fields and non-virtual bases.
EnterDtorCleanups(Dtor, Dtor_Base);
@@ -1434,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) {
@@ -1447,7 +1490,7 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
AssignmentMemcpyizer AM(*this, AssignOp, Args);
for (auto *I : RootCS->body())
- AM.emitAssignment(I);
+ AM.emitAssignment(I);
AM.finish();
}
@@ -1508,7 +1551,7 @@ namespace {
LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
LValue LV = CGF.EmitLValueForField(ThisLV, field);
assert(LV.isSimple());
-
+
CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
flags.isForNormalCleanup() && useEHCleanupForArray);
}
@@ -1526,7 +1569,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
// The deleting-destructor phase just needs to call the appropriate
// operator delete that Sema picked up.
if (DtorType == Dtor_Deleting) {
- assert(DD->getOperatorDelete() &&
+ assert(DD->getOperatorDelete() &&
"operator delete missing - EnterDtorCleanups");
if (CXXStructorImplicitParamValue) {
// If there is an implicit param to the deleting dtor, it's a boolean
@@ -1553,7 +1596,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
-
+
// Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
@@ -1567,15 +1610,15 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
}
assert(DtorType == Dtor_Base);
-
+
// Destroy non-virtual bases.
for (const auto &Base : ClassDecl->bases()) {
// Ignore virtual bases.
if (Base.isVirtual())
continue;
-
+
CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();
-
+
// Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
@@ -1656,7 +1699,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB);
EmitBlock(loopBB);
}
-
+
// Find the end of the array.
llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements,
"arrayctor.end");
@@ -1676,15 +1719,15 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
// Zero initialize the storage, if requested.
if (zeroInitialize)
EmitNullInitialization(cur, type);
-
- // C++ [class.temporary]p4:
+
+ // C++ [class.temporary]p4:
// There are two contexts in which temporaries are destroyed at a different
// point than the end of the full-expression. The first context is when a
- // default constructor is called to initialize an element of an array.
- // If the constructor has one or more default arguments, the destruction of
- // every temporary created in a default argument expression is sequenced
+ // default constructor is called to initialize an element of an array.
+ // If the constructor has one or more default arguments, the destruction of
+ // every temporary created in a default argument expression is sequenced
// before the construction of the next array element, if any.
-
+
{
RunCleanupsScope Scope(*this);
@@ -1733,33 +1776,32 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
bool ForVirtualBase,
bool Delegating, llvm::Value *This,
const CXXConstructExpr *E) {
- // If this is a trivial constructor, just emit what's needed.
- if (D->isTrivial() && !D->getParent()->mayInsertExtraPadding()) {
- if (E->getNumArgs() == 0) {
- // Trivial default constructor, no codegen required.
- assert(D->isDefaultConstructor() &&
- "trivial 0-arg ctor not a default ctor");
- return;
- }
+ // C++11 [class.mfct.non-static]p2:
+ // If a non-static member function of a class X is called for an object that
+ // is not of type X, or of a type derived from X, the behavior is undefined.
+ // FIXME: Provide a source location here.
+ EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), This,
+ getContext().getRecordType(D->getParent()));
+
+ if (D->isTrivial() && D->isDefaultConstructor()) {
+ assert(E->getNumArgs() == 0 && "trivial default ctor with args");
+ return;
+ }
+ // If this is a trivial constructor, just emit what's needed. If this is a
+ // union copy constructor, we must emit a memcpy, because the AST does not
+ // model that copy.
+ if (isMemcpyEquivalentSpecialMember(D)) {
assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
- assert(D->isCopyOrMoveConstructor() &&
- "trivial 1-arg ctor not a copy/move ctor");
const Expr *Arg = E->getArg(0);
- QualType Ty = Arg->getType();
+ QualType SrcTy = Arg->getType();
llvm::Value *Src = EmitLValue(Arg).getAddress();
- EmitAggregateCopy(This, Src, Ty);
+ QualType DestTy = getContext().getTypeDeclType(D->getParent());
+ EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
return;
}
- // C++11 [class.mfct.non-static]p2:
- // If a non-static member function of a class X is called for an object that
- // is not of type X, or of a type derived from X, the behavior is undefined.
- // FIXME: Provide a source location here.
- EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), This,
- getContext().getRecordType(D->getParent()));
-
CallArgList Args;
// Push the this ptr.
@@ -1784,25 +1826,26 @@ void
CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
llvm::Value *This, llvm::Value *Src,
const CXXConstructExpr *E) {
- if (D->isTrivial() &&
- !D->getParent()->mayInsertExtraPadding()) {
+ if (isMemcpyEquivalentSpecialMember(D)) {
assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
assert(D->isCopyOrMoveConstructor() &&
"trivial 1-arg ctor not a copy/move ctor");
- EmitAggregateCopy(This, Src, E->arg_begin()->getType());
+ EmitAggregateCopyCtor(This, Src,
+ getContext().getTypeDeclType(D->getParent()),
+ E->arg_begin()->getType());
return;
}
llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, StructorType::Complete);
assert(D->isInstance() &&
"Trying to emit a member call expr on a static method!");
-
+
const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
-
+
CallArgList Args;
-
+
// Push the this ptr.
Args.add(RValue::get(This), D->getThisType(getContext()));
-
+
// Push the src ptr.
QualType QT = *(FPT->param_type_begin());
llvm::Type *t = CGM.getTypes().ConvertType(QT);
@@ -1945,10 +1988,18 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
}
void
-CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
+CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
const CXXRecordDecl *VTableClass) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // Don't initialize the vtable pointer if the class is marked with the
+ // 'novtable' attribute.
+ if ((RD == VTableClass || RD == NearestVBase) &&
+ VTableClass->hasAttr<MSNoVTableAttr>())
+ return;
+
// Compute the address point.
bool NeedsVirtualOffset;
llvm::Value *VTableAddressPoint =
@@ -1960,7 +2011,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
// Compute where to store the address point.
llvm::Value *VirtualOffset = nullptr;
CharUnits NonVirtualOffset = CharUnits::Zero();
-
+
if (NeedsVirtualOffset) {
// We need to use the virtual base offset offset because the virtual base
// might have a different offset in the most derived class.
@@ -1973,12 +2024,12 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
// We can just use the base offset in the complete class.
NonVirtualOffset = Base.getBaseOffset();
}
-
+
// Apply the offsets.
llvm::Value *VTableField = LoadCXXThis();
-
+
if (!NonVirtualOffset.isZero() || VirtualOffset)
- VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField,
+ VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField,
NonVirtualOffset,
VirtualOffset);
@@ -1995,7 +2046,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
}
void
-CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
+CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
@@ -2008,7 +2059,7 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
VTableClass);
}
-
+
const CXXRecordDecl *RD = Base.getBase();
// Traverse bases.
@@ -2029,7 +2080,7 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
if (!VBases.insert(BaseDecl).second)
continue;
- const ASTRecordLayout &Layout =
+ const ASTRecordLayout &Layout =
getContext().getASTRecordLayout(VTableClass);
BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
@@ -2039,15 +2090,15 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
- BaseOffsetFromNearestVBase =
+ BaseOffsetFromNearestVBase =
OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
}
-
- InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
+
+ InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
I.isVirtual() ? BaseDecl : NearestVBase,
BaseOffsetFromNearestVBase,
- BaseDeclIsNonVirtualPrimaryBase,
+ BaseDeclIsNonVirtualPrimaryBase,
VTableClass, VBases);
}
}
@@ -2059,7 +2110,7 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
// Initialize the vtable pointers for this class and all of its bases.
VisitedVirtualBasesSetTy VBases;
- InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
+ InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
/*NearestVBase=*/nullptr,
/*OffsetFromNearestVBase=*/CharUnits::Zero(),
/*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases);
@@ -2076,6 +2127,149 @@ llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This,
return VTable;
}
+// If a class has a single non-virtual base and does not introduce or override
+// virtual member functions or fields, it will have the same layout as its base.
+// This function returns the least derived such class.
+//
+// Casting an instance of a base class to such a derived class is technically
+// undefined behavior, but it is a relatively common hack for introducing member
+// functions on class instances with specific properties (e.g. llvm::Operator)
+// that works under most compilers and should not have security implications, so
+// we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict.
+static const CXXRecordDecl *
+LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
+ if (!RD->field_empty())
+ return RD;
+
+ if (RD->getNumVBases() != 0)
+ return RD;
+
+ if (RD->getNumBases() != 1)
+ return RD;
+
+ for (const CXXMethodDecl *MD : RD->methods()) {
+ if (MD->isVirtual()) {
+ // Virtual member functions are only ok if they are implicit destructors
+ // because the implicit destructor will have the same semantics as the
+ // base class's destructor if no fields are added.
+ if (isa<CXXDestructorDecl>(MD) && MD->isImplicit())
+ continue;
+ return RD;
+ }
+ }
+
+ return LeastDerivedClassWithSameLayout(
+ RD->bases_begin()->getType()->getAsCXXRecordDecl());
+}
+
+void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXMethodDecl *MD,
+ llvm::Value *VTable,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
+ const CXXRecordDecl *ClassDecl = MD->getParent();
+ if (!SanOpts.has(SanitizerKind::CFICastStrict))
+ ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
+
+ EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
+}
+
+void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
+ llvm::Value *Derived,
+ bool MayBeNull,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ auto *ClassTy = T->getAs<RecordType>();
+ if (!ClassTy)
+ return;
+
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassTy->getDecl());
+
+ if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
+ return;
+
+ SmallString<64> MangledName;
+ llvm::raw_svector_ostream Out(MangledName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(T.getUnqualifiedType(),
+ Out);
+
+ // Blacklist based on the mangled type.
+ if (CGM.getContext().getSanitizerBlacklist().isBlacklistedType(Out.str()))
+ return;
+
+ if (!SanOpts.has(SanitizerKind::CFICastStrict))
+ ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
+
+ llvm::BasicBlock *ContBlock = 0;
+
+ if (MayBeNull) {
+ llvm::Value *DerivedNotNull =
+ Builder.CreateIsNotNull(Derived, "cast.nonnull");
+
+ llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check");
+ ContBlock = createBasicBlock("cast.cont");
+
+ Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);
+
+ EmitBlock(CheckBlock);
+ }
+
+ llvm::Value *VTable = GetVTablePtr(Derived, Int8PtrTy);
+ EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
+
+ if (MayBeNull) {
+ Builder.CreateBr(ContBlock);
+ EmitBlock(ContBlock);
+ }
+}
+
+void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
+ llvm::Value *VTable,
+ CFITypeCheckKind TCK,
+ SourceLocation Loc) {
+ if (CGM.IsCFIBlacklistedRecord(RD))
+ return;
+
+ SanitizerScope SanScope(this);
+
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out);
+
+ llvm::Value *BitSetName = llvm::MetadataAsValue::get(
+ getLLVMContext(), llvm::MDString::get(getLLVMContext(), Out.str()));
+
+ llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
+ llvm::Value *BitSetTest =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
+ {CastedVTable, BitSetName});
+
+ SanitizerMask M;
+ switch (TCK) {
+ case CFITCK_VCall:
+ M = SanitizerKind::CFIVCall;
+ break;
+ case CFITCK_NVCall:
+ M = SanitizerKind::CFINVCall;
+ break;
+ case CFITCK_DerivedCast:
+ M = SanitizerKind::CFIDerivedCast;
+ break;
+ case CFITCK_UnrelatedCast:
+ M = SanitizerKind::CFIUnrelatedCast;
+ break;
+ }
+
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
+ llvm::ConstantInt::get(Int8Ty, TCK),
+ };
+ EmitCheck(std::make_pair(BitSetTest, M), "cfi_bad_type", StaticData,
+ CastedVTable);
+}
// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
// quite what we want.
@@ -2140,7 +2334,7 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
// This is a record decl. We know the type and can devirtualize it.
return VD->getType()->isRecordType();
}
-
+
return false;
}
@@ -2154,14 +2348,14 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
// We can always devirtualize calls on temporary object expressions.
if (isa<CXXConstructExpr>(Base))
return true;
-
+
// And calls on bound temporaries.
if (isa<CXXBindTemporaryExpr>(Base))
return true;
-
+
// Check if this is a call expr that returns a record type.
if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
- return CE->getCallReturnType()->isRecordType();
+ return CE->getCallReturnType(getContext())->isRecordType();
// We can't devirtualize the call.
return false;
@@ -2190,7 +2384,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// We don't need to separately arrange the call arguments because
// the call can't be variadic anyway --- it's impossible to forward
// variadic arguments.
-
+
// Now emit our call.
RValue RV = EmitCall(calleeFnInfo, callee, returnSlot,
callArgs, callOperator);
@@ -2218,7 +2412,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
for (auto param : BD->params())
EmitDelegateCallArg(CallArgs, param, param->getLocStart());
- assert(!Lambda->isGenericLambda() &&
+ assert(!Lambda->isGenericLambda() &&
"generic lambda interconversion to block not implemented");
EmitForwardingCallToLambda(Lambda->getLambdaCallOperator(), CallArgs);
}
@@ -2256,7 +2450,7 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
void *InsertPos = nullptr;
- FunctionDecl *CorrespondingCallOpSpecialization =
+ FunctionDecl *CorrespondingCallOpSpecialization =
CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
assert(CorrespondingCallOpSpecialization);
CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index 18ed3e5..d97e405 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -52,8 +52,10 @@ DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
llvm::StructType::get(V.first->getType(), V.second->getType(),
(void*) nullptr);
llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
- CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0));
- CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1));
+ CGF.Builder.CreateStore(V.first,
+ CGF.Builder.CreateStructGEP(ComplexTy, addr, 0));
+ CGF.Builder.CreateStore(V.second,
+ CGF.Builder.CreateStructGEP(ComplexTy, addr, 1));
return saved_type(addr, ComplexAddress);
}
@@ -82,9 +84,9 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
case ComplexAddress: {
llvm::Value *real =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 0));
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 0));
llvm::Value *imag =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 1));
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 1));
return RValue::getComplex(real, imag);
}
}
@@ -123,6 +125,17 @@ char *EHScopeStack::allocate(size_t Size) {
return StartOfData;
}
+bool EHScopeStack::containsOnlyLifetimeMarkers(
+ EHScopeStack::stable_iterator Old) const {
+ for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) {
+ EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*it);
+ if (!cleanup || !cleanup->isLifetimeMarker())
+ return false;
+ }
+
+ return true;
+}
+
EHScopeStack::stable_iterator
EHScopeStack::getInnermostActiveNormalCleanup() const {
for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end();
@@ -469,8 +482,14 @@ static void EmitCleanup(CodeGenFunction &CGF,
EHScopeStack::Cleanup *Fn,
EHScopeStack::Cleanup::Flags flags,
llvm::Value *ActiveFlag) {
- // EH cleanups always occur within a terminate scope.
- if (flags.isForEHCleanup()) CGF.EHStack.pushTerminate();
+ // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't
+ // have this behavior, and the Microsoft C++ runtime will call terminate for
+ // us if the cleanup throws.
+ bool PushedTerminate = false;
+ if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) {
+ CGF.EHStack.pushTerminate();
+ PushedTerminate = true;
+ }
// If there's an active flag, load it and skip the cleanup if it's
// false.
@@ -493,7 +512,8 @@ static void EmitCleanup(CodeGenFunction &CGF,
CGF.EmitBlock(ContBB);
// Leave the terminate scope.
- if (flags.isForEHCleanup()) CGF.EHStack.popTerminate();
+ if (PushedTerminate)
+ CGF.EHStack.popTerminate();
}
static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
@@ -739,7 +759,15 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
Scope.getNumBranchAfters() == 1) {
assert(!BranchThroughDest || !IsActive);
- // TODO: clean up the possibly dead stores to the cleanup dest slot.
+ // Clean up the possibly dead store to the cleanup dest slot.
+ llvm::Instruction *NormalCleanupDestSlot =
+ cast<llvm::Instruction>(getNormalCleanupDestSlot());
+ if (NormalCleanupDestSlot->hasOneUse()) {
+ NormalCleanupDestSlot->user_back()->eraseFromParent();
+ NormalCleanupDestSlot->eraseFromParent();
+ NormalCleanupDest = nullptr;
+ }
+
llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter));
@@ -861,8 +889,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// Emit the EH cleanup if required.
if (RequiresEHCleanup) {
- ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
-
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
EmitBlock(EHEntry);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
index dd156c6..81c6412 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
@@ -62,6 +62,9 @@ protected:
/// Whether this cleanup is currently active.
unsigned IsActive : 1;
+ /// Whether this cleanup is a lifetime marker
+ unsigned IsLifetimeMarker : 1;
+
/// Whether the normal cleanup should test the activation flag.
unsigned TestFlagInNormalCleanup : 1;
@@ -75,7 +78,7 @@ protected:
/// The number of fixups required by enclosing scopes (not including
/// this one). If this is the top cleanup scope, all the fixups
/// from this index onwards belong to this scope.
- unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13
+ unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 13
};
class FilterBitFields {
@@ -272,6 +275,7 @@ public:
CleanupBits.IsNormalCleanup = isNormal;
CleanupBits.IsEHCleanup = isEH;
CleanupBits.IsActive = isActive;
+ CleanupBits.IsLifetimeMarker = false;
CleanupBits.TestFlagInNormalCleanup = false;
CleanupBits.TestFlagInEHCleanup = false;
CleanupBits.CleanupSize = cleanupSize;
@@ -284,19 +288,20 @@ public:
delete ExtInfo;
}
// Objects of EHCleanupScope are not destructed. Use Destroy().
- ~EHCleanupScope() LLVM_DELETED_FUNCTION;
+ ~EHCleanupScope() = delete;
bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; }
llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
bool isEHCleanup() const { return CleanupBits.IsEHCleanup; }
- llvm::BasicBlock *getEHBlock() const { return getCachedEHDispatchBlock(); }
- void setEHBlock(llvm::BasicBlock *BB) { setCachedEHDispatchBlock(BB); }
bool isActive() const { return CleanupBits.IsActive; }
void setActive(bool A) { CleanupBits.IsActive = A; }
+ bool isLifetimeMarker() const { return CleanupBits.IsLifetimeMarker; }
+ void setLifetimeMarker() { CleanupBits.IsLifetimeMarker = true; }
+
llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index 978e1bb..93a2287 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -27,6 +27,8 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Constants.h"
@@ -52,35 +54,48 @@ CGDebugInfo::~CGDebugInfo() {
"Region stack mismatch, stack not empty!");
}
-ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF)
- : ApplyDebugLocation(CGF) {
- if (auto *DI = CGF.getDebugInfo()) {
- // Construct a location that has a valid scope, but no line info.
- assert(!DI->LexicalBlockStack.empty());
- llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
- CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
- }
+ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
+ SourceLocation TemporaryLocation)
+ : CGF(CGF) {
+ init(TemporaryLocation);
}
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation,
- bool ForceColumnInfo)
+ bool DefaultToEmpty,
+ SourceLocation TemporaryLocation)
: CGF(CGF) {
+ init(TemporaryLocation, DefaultToEmpty);
+}
+
+void ApplyDebugLocation::init(SourceLocation TemporaryLocation,
+ bool DefaultToEmpty) {
if (auto *DI = CGF.getDebugInfo()) {
OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (TemporaryLocation.isInvalid())
- CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
- else
- DI->EmitLocation(CGF.Builder, TemporaryLocation, ForceColumnInfo);
+ if (TemporaryLocation.isInvalid()) {
+ if (DefaultToEmpty)
+ CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ else {
+ // Construct a location that has a valid scope, but no line info.
+ assert(!DI->LexicalBlockStack.empty());
+ CGF.Builder.SetCurrentDebugLocation(
+ llvm::DebugLoc::get(0, 0, DI->LexicalBlockStack.back()));
+ }
+ } else
+ DI->EmitLocation(CGF.Builder, TemporaryLocation);
}
}
+ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E)
+ : CGF(CGF) {
+ init(E->getExprLoc());
+}
+
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
: CGF(CGF) {
if (CGF.getDebugInfo()) {
OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (!Loc.isUnknown())
- CGF.Builder.SetCurrentDebugLocation(Loc);
+ if (Loc)
+ CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
}
}
@@ -88,11 +103,9 @@ ApplyDebugLocation::~ApplyDebugLocation() {
// Query CGF so the location isn't overwritten when location updates are
// temporarily disabled (for C++ default function arguments)
if (CGF.getDebugInfo())
- CGF.Builder.SetCurrentDebugLocation(OriginalLocation);
+ 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())
@@ -107,37 +120,32 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
return;
SourceManager &SM = CGM.getContext().getSourceManager();
- llvm::DIScope Scope(LexicalBlockStack.back());
+ auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
- if (PCLoc.isInvalid() || Scope.getFilename() == PCLoc.getFilename())
+ if (PCLoc.isInvalid() || Scope->getFilename() == PCLoc.getFilename())
return;
- if (Scope.isLexicalBlockFile()) {
- llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(Scope);
- llvm::DIDescriptor D = DBuilder.createLexicalBlockFile(
- LBF.getScope(), getOrCreateFile(CurLoc));
- llvm::MDNode *N = D;
+ if (auto *LBF = dyn_cast<llvm::DILexicalBlockFile>(Scope)) {
LexicalBlockStack.pop_back();
- LexicalBlockStack.emplace_back(N);
- } else if (Scope.isLexicalBlock() || Scope.isSubprogram()) {
- llvm::DIDescriptor D =
- DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
- llvm::MDNode *N = D;
+ LexicalBlockStack.emplace_back(DBuilder.createLexicalBlockFile(
+ LBF->getScope(), getOrCreateFile(CurLoc)));
+ } else if (isa<llvm::DILexicalBlock>(Scope) ||
+ isa<llvm::DISubprogram>(Scope)) {
LexicalBlockStack.pop_back();
- LexicalBlockStack.emplace_back(N);
+ LexicalBlockStack.emplace_back(
+ DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc)));
}
}
-/// getContextDescriptor - Get context info for the decl.
-llvm::DIScope CGDebugInfo::getContextDescriptor(const Decl *Context) {
+llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
if (!Context)
return TheCU;
auto I = RegionMap.find(Context);
if (I != RegionMap.end()) {
llvm::Metadata *V = I->second;
- return llvm::DIScope(dyn_cast_or_null<llvm::MDNode>(V));
+ return dyn_cast_or_null<llvm::DIScope>(V);
}
// Check namespace.
@@ -151,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();
@@ -209,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
@@ -233,18 +235,17 @@ 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) {
+llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -253,22 +254,20 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (it != DIFileCache.end()) {
// Verify that the information still exists.
if (llvm::Metadata *V = it->second)
- return llvm::DIFile(cast<llvm::MDNode>(V));
+ return cast<llvm::DIFile>(V);
}
- llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
+ llvm::DIFile *F =
+ DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
DIFileCache[fname].reset(F);
return F;
}
-/// getOrCreateMainFile - Get the file info for main compile unit.
-llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+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;
@@ -277,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)
@@ -302,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
@@ -369,12 +366,11 @@ void CGDebugInfo::CreateCompileUnit() {
DebugKind <= CodeGenOptions::DebugLineTablesOnly
? llvm::DIBuilder::LineTablesOnly
: llvm::DIBuilder::FullDebug,
+ 0 /* DWOid */,
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::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::dwarf::TypeKind Encoding;
StringRef BTName;
switch (BT->getKind()) {
@@ -386,7 +382,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::NullPtr:
return DBuilder.createNullPtrType();
case BuiltinType::Void:
- return llvm::DIType();
+ return nullptr;
case BuiltinType::ObjCClass:
if (!ClassTy)
ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
@@ -409,11 +405,11 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
+ auto *ISATy = DBuilder.createPointerType(ClassTy, Size);
ObjTy =
DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(),
- 0, 0, 0, 0, llvm::DIType(), llvm::DIArray());
+ 0, 0, 0, 0, nullptr, llvm::DINodeArray());
DBuilder.replaceArrays(
ObjTy,
@@ -510,11 +506,10 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
- llvm::DIType DbgTy = DBuilder.createBasicType(BTName, Size, Align, Encoding);
- return DbgTy;
+ return DBuilder.createBasicType(BTName, Size, Align, Encoding);
}
-llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
+llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
// Bit size, align and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
@@ -522,15 +517,11 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- llvm::DIType DbgTy =
- DBuilder.createBasicType("complex", Size, Align, Encoding);
-
- return DbgTy;
+ 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) {
+llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
+ llvm::DIFile *Unit) {
QualifierCollector Qc;
const Type *T = Qc.strip(Ty);
@@ -556,17 +547,15 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
return getOrCreateType(QualType(T, 0), Unit);
}
- llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
+ auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
-
- return DbgTy;
+ return DBuilder.createQualifiedType(Tag, FromTy);
}
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
+ llvm::DIFile *Unit) {
// The frontend treats 'id' as a typedef to an ObjCObjectType,
// whereas 'id<protocol>' is treated as an ObjCPointerType. For the
@@ -574,28 +563,39 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
if (Ty->isObjCQualifiedIdType())
return getOrCreateType(CGM.getContext().getObjCIdType(), Unit);
- llvm::DIType DbgTy = CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type,
- Ty, Ty->getPointeeType(), Unit);
- return DbgTy;
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
+ llvm::DIFile *Unit) {
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
}
+/// \return whether a C++ mangling exists for the type defined by TD.
+static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
+ switch (TheCU->getSourceLanguage()) {
+ case llvm::dwarf::DW_LANG_C_plus_plus:
+ return true;
+ case llvm::dwarf::DW_LANG_ObjC_plus_plus:
+ return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
+ default:
+ return false;
+ }
+}
+
/// In C++ mode, types have linkage, so we can rely on the ODR and
/// on their mangled names, if they're external.
static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
CodeGenModule &CGM,
- llvm::DICompileUnit TheCU) {
+ llvm::DICompileUnit *TheCU) {
SmallString<256> FullName;
- // FIXME: ODR should apply to ObjC++ exactly the same wasy it does to C++.
- // For now, only apply ODR with C++.
const TagDecl *TD = Ty->getDecl();
- if (TheCU.getLanguage() != llvm::dwarf::DW_LANG_C_plus_plus ||
- !TD->isExternallyVisible())
+
+ if (!hasCXXMangling(TD, TheCU) || !TD->isExternallyVisible())
return FullName;
+
// Microsoft Mangler does not have support for mangleCXXRTTIName yet.
if (CGM.getTarget().getCXXABI().isMicrosoft())
return FullName;
@@ -608,41 +608,56 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
return FullName;
}
-// Creates a forward declaration for a RecordDecl in the given context.
-llvm::DICompositeType
-CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
- llvm::DIDescriptor Ctx) {
- const RecordDecl *RD = Ty->getDecl();
- if (llvm::DIType T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
- return llvm::DICompositeType(T);
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
- unsigned Line = getLineNumber(RD->getLocation());
- StringRef RDName = getClassName(RD);
-
- llvm::dwarf::Tag Tag;
+/// \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())
Tag = llvm::dwarf::DW_TAG_structure_type;
else if (RD->isUnion())
Tag = llvm::dwarf::DW_TAG_union_type;
else {
+ // FIXME: This could be a struct type giving a default visibility different
+ // than C++ class type, but needs llvm metadata changes first.
assert(RD->isClass());
Tag = llvm::dwarf::DW_TAG_class_type;
}
+ return Tag;
+}
+
+llvm::DICompositeType *
+CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
+ llvm::DIScope *Ctx) {
+ const RecordDecl *RD = Ty->getDecl();
+ if (llvm::DIType *T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
+ return cast<llvm::DICompositeType>(T);
+ llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
+ unsigned Line = getLineNumber(RD->getLocation());
+ StringRef RDName = getClassName(RD);
+
+ uint64_t Size = 0;
+ uint64_t Align = 0;
+
+ const RecordDecl *D = RD->getDefinition();
+ if (D && D->isCompleteDefinition()) {
+ Size = CGM.getContext().getTypeSize(Ty);
+ Align = CGM.getContext().getTypeAlign(Ty);
+ }
// Create the type.
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- llvm::DICompositeType RetTy = DBuilder.createReplaceableForwardDecl(
- Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0, FullName);
+ llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType(
+ getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align,
+ llvm::DINode::FlagFwdDecl, FullName);
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
return RetTy;
}
-llvm::DIType CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
- const Type *Ty,
- QualType PointeeTy,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
+ const Type *Ty,
+ QualType PointeeTy,
+ llvm::DIFile *Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit));
@@ -658,8 +673,8 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
Align);
}
-llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
- llvm::DIType &Cache) {
+llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
+ llvm::DIType *&Cache) {
if (Cache)
return Cache;
Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name,
@@ -669,18 +684,13 @@ llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
return Cache;
}
-llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
- llvm::DIFile Unit) {
- if (BlockLiteralGeneric)
- return BlockLiteralGeneric;
-
+llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
+ llvm::DIFile *Unit) {
SmallVector<llvm::Metadata *, 8> EltTys;
- llvm::DIType FieldTy;
QualType FType;
uint64_t FieldSize, FieldOffset;
unsigned FieldAlign;
- llvm::DIArray Elements;
- llvm::DIType EltTy, DescTy;
+ llvm::DINodeArray Elements;
FieldOffset = 0;
FType = CGM.getContext().UnsignedLongTy;
@@ -690,17 +700,17 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
Elements = DBuilder.getOrCreateArray(EltTys);
EltTys.clear();
- unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
- unsigned LineNo = getLineNumber(CurLoc);
+ unsigned Flags = llvm::DINode::FlagAppleBlock;
+ unsigned LineNo = 0;
- EltTy = DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo,
- FieldOffset, 0, Flags, llvm::DIType(),
- Elements);
+ auto *EltTy =
+ DBuilder.createStructType(Unit, "__block_descriptor", nullptr, LineNo,
+ FieldOffset, 0, Flags, nullptr, Elements);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- DescTy = DBuilder.createPointerType(EltTy, Size);
+ auto *DescTy = DBuilder.createPointerType(EltTy, Size);
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -712,29 +722,30 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- FieldTy = DescTy;
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy =
- DBuilder.createMemberType(Unit, "__descriptor", Unit, LineNo, FieldSize,
- FieldAlign, FieldOffset, 0, FieldTy);
- EltTys.push_back(FieldTy);
+ EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo,
+ FieldSize, FieldAlign, FieldOffset,
+ 0, DescTy));
FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
- EltTy = DBuilder.createStructType(Unit, "__block_literal_generic", Unit,
- LineNo, FieldOffset, 0, Flags,
- llvm::DIType(), Elements);
+ // 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, "", 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,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
+ llvm::DIFile *Unit) {
assert(Ty->isTypeAlias());
- llvm::DIType Src = getOrCreateType(Ty->getAliasedType(), Unit);
+ llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit);
SmallString<128> NS;
llvm::raw_svector_ostream OS(NS);
@@ -749,35 +760,26 @@ llvm::DIType CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl();
SourceLocation Loc = AliasDecl->getLocation();
- llvm::DIFile File = getOrCreateFile(Loc);
- unsigned Line = getLineNumber(Loc);
-
- llvm::DIDescriptor Ctxt =
- getContextDescriptor(cast<Decl>(AliasDecl->getDeclContext()));
-
- return DBuilder.createTypedef(Src, internString(OS.str()), File, Line, Ctxt);
+ return DBuilder.createTypedef(
+ Src, internString(OS.str()), getOrCreateFile(Loc), getLineNumber(Loc),
+ getContextDescriptor(cast<Decl>(AliasDecl->getDeclContext())));
}
-llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
- // Typedefs are derived from some other type. If we have a typedef of a
- // typedef, make sure to emit the whole chain.
- llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
+ llvm::DIFile *Unit) {
// We don't set size information, but do specify where the typedef was
// declared.
SourceLocation Loc = Ty->getDecl()->getLocation();
- llvm::DIFile File = getOrCreateFile(Loc);
- unsigned Line = getLineNumber(Loc);
- const TypedefNameDecl *TyDecl = Ty->getDecl();
-
- llvm::DIDescriptor TypedefContext =
- getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
- return DBuilder.createTypedef(Src, TyDecl->getName(), File, Line,
- TypedefContext);
+ // Typedefs are derived from some other type.
+ return DBuilder.createTypedef(
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
+ Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
+ getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())));
}
-llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
+ llvm::DIFile *Unit) {
SmallVector<llvm::Metadata *, 16> EltTys;
// Add the result type at least.
@@ -794,11 +796,11 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
EltTys.push_back(DBuilder.createUnspecifiedParameter());
}
- llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
+ llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
-/// Convert an AccessSpecifier into the corresponding DIDescriptor flag.
+/// Convert an AccessSpecifier into the corresponding DINode flag.
/// As an optimization, return 0 if the access specifier equals the
/// default for the containing type.
static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
@@ -813,25 +815,25 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
switch (Access) {
case clang::AS_private:
- return llvm::DIDescriptor::FlagPrivate;
+ return llvm::DINode::FlagPrivate;
case clang::AS_protected:
- return llvm::DIDescriptor::FlagProtected;
+ return llvm::DINode::FlagProtected;
case clang::AS_public:
- return llvm::DIDescriptor::FlagPublic;
+ return llvm::DINode::FlagPublic;
case clang::AS_none:
return 0;
}
llvm_unreachable("unexpected access enumerator");
}
-llvm::DIType CGDebugInfo::createFieldType(
+llvm::DIType *CGDebugInfo::createFieldType(
StringRef name, QualType type, uint64_t sizeInBitsOverride,
SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile tunit, llvm::DIScope scope, const RecordDecl *RD) {
- llvm::DIType debugType = getOrCreateType(type, tunit);
+ llvm::DIFile *tunit, llvm::DIScope *scope, const RecordDecl *RD) {
+ llvm::DIType *debugType = getOrCreateType(type, tunit);
// Get the location for the field.
- llvm::DIFile file = getOrCreateFile(loc);
+ llvm::DIFile *file = getOrCreateFile(loc);
unsigned line = getLineNumber(loc);
uint64_t SizeInBits = 0;
@@ -850,10 +852,9 @@ 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) {
+ llvm::DIType *RecordTy) {
// For C++11 Lambdas a Field will be the same as a Capture, but the Capture
// has the name and the location of the variable so we should iterate over
// both concurrently.
@@ -866,14 +867,14 @@ void CGDebugInfo::CollectRecordLambdaFields(
const LambdaCapture &C = *I;
if (C.capturesVariable()) {
VarDecl *V = C.getCapturedVar();
- llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
+ llvm::DIFile *VUnit = getOrCreateFile(C.getLocation());
StringRef VName = V->getName();
uint64_t SizeInBitsOverride = 0;
if (Field->isBitField()) {
SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());
assert(SizeInBitsOverride && "found named 0-width bitfield");
}
- llvm::DIType fieldType = createFieldType(
+ llvm::DIType *fieldType = createFieldType(
VName, Field->getType(), SizeInBitsOverride, C.getLocation(),
Field->getAccess(), layout.getFieldOffset(fieldno), VUnit, RecordTy,
CXXDecl);
@@ -884,9 +885,9 @@ void CGDebugInfo::CollectRecordLambdaFields(
// by using AT_object_pointer for the function and having that be
// used as 'this' for semantic references.
FieldDecl *f = *Field;
- llvm::DIFile VUnit = getOrCreateFile(f->getLocation());
+ llvm::DIFile *VUnit = getOrCreateFile(f->getLocation());
QualType type = f->getType();
- llvm::DIType fieldType = createFieldType(
+ llvm::DIType *fieldType = createFieldType(
"this", type, 0, f->getLocation(), f->getAccess(),
layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl);
@@ -895,15 +896,14 @@ void CGDebugInfo::CollectRecordLambdaFields(
}
}
-/// Helper for CollectRecordFields.
-llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
- llvm::DIType RecordTy,
- const RecordDecl *RD) {
+llvm::DIDerivedType *
+CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
+ const RecordDecl *RD) {
// Create the descriptor for the static variable, with or without
// constant initializers.
Var = Var->getCanonicalDecl();
- llvm::DIFile VUnit = getOrCreateFile(Var->getLocation());
- llvm::DIType VTy = getOrCreateType(Var->getType(), VUnit);
+ llvm::DIFile *VUnit = getOrCreateFile(Var->getLocation());
+ llvm::DIType *VTy = getOrCreateType(Var->getType(), VUnit);
unsigned LineNumber = getLineNumber(Var->getLocation());
StringRef VName = Var->getName();
@@ -919,16 +919,15 @@ llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
}
unsigned Flags = getAccessFlag(Var->getAccess(), RD);
- llvm::DIDerivedType GV = DBuilder.createStaticMemberType(
+ llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
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,
+ const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit,
+ SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy,
const RecordDecl *RD) {
StringRef name = field->getName();
QualType type = field->getType();
@@ -943,19 +942,17 @@ void CGDebugInfo::CollectRecordNormalField(
assert(SizeInBitsOverride && "found named 0-width bitfield");
}
- llvm::DIType fieldType =
+ llvm::DIType *fieldType =
createFieldType(name, type, SizeInBitsOverride, field->getLocation(),
field->getAccess(), OffsetInBits, tunit, RecordTy, RD);
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,
+ const RecordDecl *record, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements,
- llvm::DICompositeType RecordTy) {
+ llvm::DICompositeType *RecordTy) {
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
if (CXXDecl && CXXDecl->isLambda())
@@ -975,8 +972,7 @@ void CGDebugInfo::CollectRecordFields(
if (MI != StaticDataMemberCache.end()) {
assert(MI->second &&
"Static data member declaration should still exist");
- elements.push_back(
- llvm::DIDerivedType(cast<llvm::MDNode>(MI->second)));
+ elements.push_back(cast<llvm::DIDerivedTypeBase>(MI->second));
} else {
auto Field = CreateRecordStaticField(V, RecordTy, record);
elements.push_back(Field);
@@ -991,30 +987,29 @@ 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::DICompositeType
+llvm::DISubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile Unit) {
+ llvm::DIFile *Unit) {
const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
if (Method->isStatic())
- return llvm::DICompositeType(getOrCreateType(QualType(Func, 0), Unit));
+ return cast_or_null<llvm::DISubroutineType>(
+ getOrCreateType(QualType(Func, 0), Unit));
return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
Func, Unit);
}
-llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
- QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) {
+llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
+ QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile *Unit) {
// Add "this" pointer.
- llvm::DITypeArray Args = llvm::DISubroutineType(
- getOrCreateType(QualType(Func, 0), Unit)).getTypeArray();
- assert(Args.getNumElements() && "Invalid number of arguments!");
+ llvm::DITypeRefArray Args(
+ cast<llvm::DISubroutineType>(getOrCreateType(QualType(Func, 0), Unit))
+ ->getTypeArray());
+ assert(Args.size() && "Invalid number of arguments!");
SmallVector<llvm::Metadata *, 16> Elts;
// First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(Args.getElement(0));
+ Elts.push_back(Args[0]);
// "this" pointer is always first argument.
const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl();
@@ -1025,8 +1020,8 @@ llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
- llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
- llvm::DIType ThisPtrType =
+ llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit);
+ llvm::DIType *ThisPtrType =
DBuilder.createPointerType(PointeeType, Size, Align);
TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
// TODO: This and the artificial type below are misleading, the
@@ -1035,23 +1030,23 @@ llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
Elts.push_back(ThisPtrType);
} else {
- llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);
+ llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit);
TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
Elts.push_back(ThisPtrType);
}
// Copy rest of the arguments.
- for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
- Elts.push_back(Args.getElement(i));
+ for (unsigned i = 1, e = Args.size(); i != e; ++i)
+ Elts.push_back(Args[i]);
- llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
+ llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
unsigned Flags = 0;
if (Func->getExtProtoInfo().RefQualifier == RQ_LValue)
- Flags |= llvm::DIDescriptor::FlagLValueReference;
+ Flags |= llvm::DINode::FlagLValueReference;
if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
- Flags |= llvm::DIDescriptor::FlagRValueReference;
+ Flags |= llvm::DINode::FlagRValueReference;
return DBuilder.createSubroutineType(Unit, EltTypeArray, Flags);
}
@@ -1066,16 +1061,13 @@ static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
return false;
}
-/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
-/// a single member function GlobalDecl.
-llvm::DISubprogram
-CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
- llvm::DIFile Unit, llvm::DIType RecordTy) {
+llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
+ const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
bool IsCtorOrDtor =
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
StringRef MethodName = getFunctionName(Method);
- llvm::DICompositeType MethodTy = getOrCreateMethodType(Method, Unit);
+ llvm::DISubroutineType *MethodTy = getOrCreateMethodType(Method, Unit);
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
// make sense to give a single ctor/dtor a linkage name.
@@ -1084,7 +1076,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
MethodLinkageName = CGM.getMangledName(Method);
// Get the location for the method.
- llvm::DIFile MethodDefUnit;
+ llvm::DIFile *MethodDefUnit = nullptr;
unsigned MethodLine = 0;
if (!Method->isImplicit()) {
MethodDefUnit = getOrCreateFile(Method->getLocation());
@@ -1092,7 +1084,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
}
// Collect virtual method info.
- llvm::DIType ContainingType;
+ llvm::DIType *ContainingType = nullptr;
unsigned Virtuality = 0;
unsigned VIndex = 0;
@@ -1115,41 +1107,38 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
unsigned Flags = 0;
if (Method->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DINode::FlagArtificial;
Flags |= getAccessFlag(Method->getAccess(), Method->getParent());
if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
+ Flags |= llvm::DINode::FlagExplicit;
} else if (const CXXConversionDecl *CXXC =
dyn_cast<CXXConversionDecl>(Method)) {
if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
+ Flags |= llvm::DINode::FlagExplicit;
}
if (Method->hasPrototype())
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DINode::FlagPrototyped;
if (Method->getRefQualifier() == RQ_LValue)
- Flags |= llvm::DIDescriptor::FlagLValueReference;
+ Flags |= llvm::DINode::FlagLValueReference;
if (Method->getRefQualifier() == RQ_RValue)
- Flags |= llvm::DIDescriptor::FlagRValueReference;
+ Flags |= llvm::DINode::FlagRValueReference;
- llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
- llvm::DISubprogram SP = DBuilder.createMethod(
+ llvm::DINodeArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
+ llvm::DISubprogram *SP = DBuilder.createMethod(
RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/false, Virtuality, VIndex, ContainingType, Flags,
- CGM.getLangOpts().Optimize, nullptr, TParamsArray);
+ CGM.getLangOpts().Optimize, nullptr, TParamsArray.get());
SPCache[Method->getCanonicalDecl()].reset(SP);
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) {
+ const CXXRecordDecl *RD, llvm::DIFile *Unit,
+ SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) {
// Since we want more than just the individual member decls if we
// have templated functions iterate over every declaration to gather
@@ -1160,12 +1149,13 @@ void CGDebugInfo::CollectCXXMemberFunctions(
// the member being added to type units by LLVM, while still allowing it
// to be emitted into the type declaration/reference inside the compile
// unit.
+ // Ditto 'nodebug' methods, for consistency with CodeGenFunction.cpp.
// FIXME: Handle Using(Shadow?)Decls here to create
// DW_TAG_imported_declarations inside the class for base decls brought into
// derived classes. GDB doesn't seem to notice/leverage these when I tried
// it, so I'm not rushing to fix this. (GCC seems to produce them, if
// referenced)
- if (!Method || Method->isImplicit())
+ if (!Method || Method->isImplicit() || Method->hasAttr<NoDebugAttr>())
continue;
if (Method->getType()->getAs<FunctionProtoType>()->getContainedAutoType())
@@ -1184,13 +1174,9 @@ 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,
+void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
- llvm::DIType RecordTy) {
-
+ llvm::DIType *RecordTy) {
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
for (const auto &BI : RD->bases()) {
unsigned BFlags = 0;
@@ -1212,24 +1198,23 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BaseOffset =
4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
}
- BFlags = llvm::DIDescriptor::FlagVirtual;
+ BFlags = llvm::DINode::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
// BI->isVirtual() and bits when not.
BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD);
- llvm::DIType DTy = DBuilder.createInheritance(
+ llvm::DIType *DTy = DBuilder.createInheritance(
RecordTy, getOrCreateType(BI.getType(), Unit), BaseOffset, BFlags);
EltTys.push_back(DTy);
}
}
-/// CollectTemplateParams - A helper function to collect template parameters.
-llvm::DIArray
+llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
- llvm::DIFile Unit) {
+ llvm::DIFile *Unit) {
SmallVector<llvm::Metadata *, 16> TemplateParams;
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
const TemplateArgument &TA = TAList[i];
@@ -1238,23 +1223,20 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
Name = TPList->getParam(i)->getName();
switch (TA.getKind()) {
case TemplateArgument::Type: {
- llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
- llvm::DITemplateTypeParameter TTP =
- DBuilder.createTemplateTypeParameter(TheCU, Name, TTy);
- TemplateParams.push_back(TTP);
+ llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
+ TemplateParams.push_back(
+ DBuilder.createTemplateTypeParameter(TheCU, Name, TTy));
} break;
case TemplateArgument::Integral: {
- llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
- llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy,
- llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral()));
- TemplateParams.push_back(TVP);
+ llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy,
+ llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())));
} break;
case TemplateArgument::Declaration: {
const ValueDecl *D = TA.getAsDecl();
QualType T = TA.getParamTypeForDecl().getDesugaredType(CGM.getContext());
- llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::DIType *TTy = getOrCreateType(T, Unit);
llvm::Constant *V = nullptr;
const CXXMethodDecl *MD;
// Variable pointer template parameters have a value that is the address
@@ -1264,7 +1246,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
// Member function pointers have special support for building them, though
// this is currently unsupported in LLVM CodeGen.
else if ((MD = dyn_cast<CXXMethodDecl>(D)) && MD->isInstance())
- V = CGM.getCXXABI().EmitMemberPointer(MD);
+ V = CGM.getCXXABI().EmitMemberFunctionPointer(MD);
else if (const auto *FD = dyn_cast<FunctionDecl>(D))
V = CGM.GetAddrOfFunction(FD);
// Member data pointers have special handling too to compute the fixed
@@ -1278,15 +1260,13 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset);
V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars);
}
- llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy,
- cast_or_null<llvm::Constant>(V->stripPointerCasts()));
- TemplateParams.push_back(TVP);
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy,
+ cast_or_null<llvm::Constant>(V->stripPointerCasts())));
} break;
case TemplateArgument::NullPtr: {
QualType T = TA.getNullPtrType();
- llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::DIType *TTy = getOrCreateType(T, Unit);
llvm::Constant *V = nullptr;
// Special case member data pointer null values since they're actually -1
// instead of zero.
@@ -1301,24 +1281,19 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
if (!V)
V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
- llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(TheCU, Name, TTy,
- cast<llvm::Constant>(V));
- TemplateParams.push_back(TVP);
- } break;
- case TemplateArgument::Template: {
- llvm::DITemplateValueParameter
- TVP = DBuilder.createTemplateTemplateParameter(
- TheCU, Name, llvm::DIType(),
- TA.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString());
- TemplateParams.push_back(TVP);
- } break;
- case TemplateArgument::Pack: {
- llvm::DITemplateValueParameter TVP = DBuilder.createTemplateParameterPack(
- TheCU, Name, llvm::DIType(),
- CollectTemplateParams(nullptr, TA.getPackAsArray(), Unit));
- TemplateParams.push_back(TVP);
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy, cast<llvm::Constant>(V)));
} break;
+ case TemplateArgument::Template:
+ TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
+ TheCU, Name, nullptr,
+ TA.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString()));
+ break;
+ case TemplateArgument::Pack:
+ TemplateParams.push_back(DBuilder.createTemplateParameterPack(
+ TheCU, Name, nullptr,
+ CollectTemplateParams(nullptr, TA.getPackAsArray(), Unit)));
+ break;
case TemplateArgument::Expression: {
const Expr *E = TA.getAsExpr();
QualType T = E->getType();
@@ -1326,11 +1301,9 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
T = CGM.getContext().getLValueReferenceType(T);
llvm::Constant *V = CGM.EmitConstantExpr(E, T);
assert(V && "Expression in template argument isn't constant");
- llvm::DIType TTy = getOrCreateType(T, Unit);
- llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy, cast<llvm::Constant>(V->stripPointerCasts()));
- TemplateParams.push_back(TVP);
+ llvm::DIType *TTy = getOrCreateType(T, Unit);
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy, cast<llvm::Constant>(V->stripPointerCasts())));
} break;
// And the following should never occur:
case TemplateArgument::TemplateExpansion:
@@ -1342,10 +1315,9 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
return DBuilder.getOrCreateArray(TemplateParams);
}
-/// CollectFunctionTemplateParams - A helper function to collect debug
-/// info for function template parameters.
-llvm::DIArray CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
- llvm::DIFile Unit) {
+llvm::DINodeArray
+CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
+ llvm::DIFile *Unit) {
if (FD->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization) {
const TemplateParameterList *TList = FD->getTemplateSpecializationInfo()
@@ -1354,13 +1326,11 @@ llvm::DIArray CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
return CollectTemplateParams(
TList, FD->getTemplateSpecializationArgs()->asArray(), Unit);
}
- return llvm::DIArray();
+ return llvm::DINodeArray();
}
-/// CollectCXXTemplateParams - A helper function to collect debug info for
-/// template parameters.
-llvm::DIArray CGDebugInfo::CollectCXXTemplateParams(
- const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile Unit) {
+llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
+ const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
// Always get the full list of parameters, not just the ones from
// the specialization.
TemplateParameterList *TPList =
@@ -1369,33 +1339,29 @@ llvm::DIArray CGDebugInfo::CollectCXXTemplateParams(
return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
-/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
-llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
- if (VTablePtrType.isValid())
+llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
+ if (VTablePtrType)
return VTablePtrType;
ASTContext &Context = CGM.getContext();
/* Function type */
llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit);
- llvm::DITypeArray SElements = DBuilder.getOrCreateTypeArray(STy);
- llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
+ llvm::DITypeRefArray SElements = DBuilder.getOrCreateTypeArray(STy);
+ llvm::DIType *SubTy = DBuilder.createSubroutineType(Unit, SElements);
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
- llvm::DIType vtbl_ptr_type =
+ llvm::DIType *vtbl_ptr_type =
DBuilder.createPointerType(SubTy, Size, 0, "__vtbl_ptr_type");
VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
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,
+void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys) {
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
@@ -1408,26 +1374,23 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
return;
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType VPTR = DBuilder.createMemberType(
+ llvm::DIType *VPTR = DBuilder.createMemberType(
Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
- llvm::DIDescriptor::FlagArtificial, getOrCreateVTablePtrType(Unit));
+ llvm::DINode::FlagArtificial, getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
}
-/// getOrCreateRecordType - Emit record type's standalone debug info.
-llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
- SourceLocation Loc) {
+llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
+ SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
- llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
+ llvm::DIType *T = getOrCreateType(RTy, getOrCreateFile(Loc));
return T;
}
-/// getOrCreateInterfaceType - Emit an objective c interface type standalone
-/// debug info.
-llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
- SourceLocation Loc) {
+llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D,
+ SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
- llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
+ llvm::DIType *T = getOrCreateType(D, getOrCreateFile(Loc));
RetainedTypes.push_back(D.getAsOpaquePtr());
return T;
}
@@ -1438,11 +1401,10 @@ void CGDebugInfo::completeType(const EnumDecl *ED) {
QualType Ty = CGM.getContext().getEnumType(ED);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
- if (I == TypeCache.end() ||
- !llvm::DIType(cast<llvm::MDNode>(I->second)).isForwardDecl())
+ if (I == TypeCache.end() || !cast<llvm::DIType>(I->second)->isForwardDecl())
return;
- llvm::DIType Res = CreateTypeDefinition(Ty->castAs<EnumType>());
- assert(!Res.isForwardDecl());
+ llvm::DIType *Res = CreateTypeDefinition(Ty->castAs<EnumType>());
+ assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -1461,8 +1423,8 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
return;
QualType Ty = CGM.getContext().getRecordType(RD);
- llvm::DIType T = getTypeOrNull(Ty);
- if (T && T.isForwardDecl())
+ llvm::DIType *T = getTypeOrNull(Ty);
+ if (T && T->isForwardDecl())
completeClassData(RD);
}
@@ -1472,11 +1434,10 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) {
QualType Ty = CGM.getContext().getRecordType(RD);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
- if (I != TypeCache.end() &&
- !llvm::DIType(cast<llvm::MDNode>(I->second)).isForwardDecl())
+ if (I != TypeCache.end() && !cast<llvm::DIType>(I->second)->isForwardDecl())
return;
- llvm::DIType Res = CreateTypeDefinition(Ty->castAs<RecordType>());
- assert(!Res.isForwardDecl());
+ llvm::DIType *Res = CreateTypeDefinition(Ty->castAs<RecordType>());
+ assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -1523,10 +1484,9 @@ static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
return false;
}
-/// CreateType - get structure or union type.
-llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
+llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
- llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));
+ llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {
if (!T)
T = getOrCreateRecordFwdDecl(
@@ -1537,11 +1497,11 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
return CreateTypeDefinition(Ty);
}
-llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
+llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
// Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
// Records and classes and unions can all be recursive. To handle them, we
// first generate a debug descriptor for the struct as a forward declaration.
@@ -1550,11 +1510,11 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DICompositeType FwdDecl(getOrCreateLimitedType(Ty, DefUnit));
- assert(FwdDecl.isCompositeType() &&
- "The debug type of a RecordType should be a llvm::DICompositeType");
+ auto *FwdDecl =
+ cast<llvm::DICompositeType>(getOrCreateLimitedType(Ty, DefUnit));
- if (FwdDecl.isForwardDecl())
+ const RecordDecl *D = RD->getDefinition();
+ if (!D || !D->isCompleteDefinition())
return FwdDecl;
if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
@@ -1586,16 +1546,19 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
LexicalBlockStack.pop_back();
RegionMap.erase(Ty->getDecl());
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
DBuilder.replaceArrays(FwdDecl, Elements);
+ if (FwdDecl->isTemporary())
+ FwdDecl =
+ llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl));
+
RegionMap[Ty->getDecl()].reset(FwdDecl);
return FwdDecl;
}
-/// CreateType - get objective-c object type.
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
+ llvm::DIFile *Unit) {
// Ignore protocols.
return getOrCreateType(Ty->getBaseType(), Unit);
}
@@ -1624,23 +1587,23 @@ 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) {
+llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
+ llvm::DIFile *Unit) {
ObjCInterfaceDecl *ID = Ty->getDecl();
if (!ID)
- return llvm::DIType();
+ return nullptr;
// Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
+ llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
- llvm::dwarf::SourceLanguage RuntimeLang = TheCU.getLanguage();
+ auto RuntimeLang =
+ static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
// If this is just a forward declaration return a special forward-declaration
// debug type since we won't be able to lay out the entire type.
ObjCInterfaceDecl *Def = ID->getDefinition();
if (!Def || !Def->getImplementation()) {
- llvm::DIType FwdDecl = DBuilder.createReplaceableForwardDecl(
+ llvm::DIType *FwdDecl = DBuilder.createReplaceableCompositeType(
llvm::dwarf::DW_TAG_structure_type, ID->getName(), TheCU, DefUnit, Line,
RuntimeLang);
ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit));
@@ -1650,12 +1613,53 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
return CreateTypeDefinition(Ty, Unit);
}
-llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
- llvm::DIFile Unit) {
+llvm::DIModule *
+CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod) {
+ auto it = ModuleRefCache.find(Mod.Signature);
+ if (it != ModuleRefCache.end())
+ return it->second;
+
+ // Macro definitions that were defined with "-D" on the command line.
+ SmallString<128> ConfigMacros;
+ {
+ llvm::raw_svector_ostream OS(ConfigMacros);
+ const auto &PPOpts = CGM.getPreprocessorOpts();
+ unsigned I = 0;
+ // Translate the macro definitions back into a commmand line.
+ for (auto &M : PPOpts.Macros) {
+ if (++I > 1)
+ OS << " ";
+ const std::string &Macro = M.first;
+ bool Undef = M.second;
+ OS << "\"-" << (Undef ? 'U' : 'D');
+ for (char c : Macro)
+ switch (c) {
+ case '\\' : OS << "\\\\"; break;
+ case '"' : OS << "\\\""; break;
+ default: OS << c;
+ }
+ OS << '\"';
+ }
+ }
+ llvm::DIBuilder DIB(CGM.getModule());
+ auto *CU = DIB.createCompileUnit(
+ TheCU->getSourceLanguage(), internString(Mod.ModuleName),
+ internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0,
+ internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature);
+ llvm::DIModule *ModuleRef =
+ DIB.createModule(CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),
+ internString(CGM.getHeaderSearchOpts().Sysroot));
+ DIB.finalize();
+ ModuleRefCache.insert(std::make_pair(Mod.Signature, ModuleRef));
+ return ModuleRef;
+}
+
+llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
+ llvm::DIFile *Unit) {
ObjCInterfaceDecl *ID = Ty->getDecl();
- llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
+ llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
- unsigned RuntimeLang = TheCU.getLanguage();
+ unsigned RuntimeLang = TheCU->getSourceLanguage();
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -1663,17 +1667,17 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
unsigned Flags = 0;
if (ID->getImplementation())
- Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
+ Flags |= llvm::DINode::FlagObjcClassComplete;
- llvm::DICompositeType RealDecl = DBuilder.createStructType(
- Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, llvm::DIType(),
- llvm::DIArray(), RuntimeLang);
+ llvm::DICompositeType *RealDecl = DBuilder.createStructType(
+ Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, nullptr,
+ llvm::DINodeArray(), RuntimeLang);
QualType QTy(Ty, 0);
TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl);
// Push the struct on region stack.
- LexicalBlockStack.emplace_back(static_cast<llvm::MDNode *>(RealDecl));
+ LexicalBlockStack.emplace_back(RealDecl);
RegionMap[Ty->getDecl()].reset(RealDecl);
// Convert all the elements.
@@ -1681,19 +1685,19 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
ObjCInterfaceDecl *SClass = ID->getSuperClass();
if (SClass) {
- llvm::DIType SClassTy =
+ llvm::DIType *SClassTy =
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
- if (!SClassTy.isValid())
- return llvm::DIType();
+ if (!SClassTy)
+ return nullptr;
- llvm::DIType InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
+ llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
// Create entries for all of the properties.
for (const auto *PD : ID->properties()) {
SourceLocation Loc = PD->getLocation();
- llvm::DIFile PUnit = getOrCreateFile(Loc);
+ llvm::DIFile *PUnit = getOrCreateFile(Loc);
unsigned PLine = getLineNumber(Loc);
ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
@@ -1711,9 +1715,9 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
unsigned FieldNo = 0;
for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
Field = Field->getNextIvar(), ++FieldNo) {
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- if (!FieldTy.isValid())
- return llvm::DIType();
+ llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
+ if (!FieldTy)
+ return nullptr;
StringRef FieldName = Field->getName();
@@ -1722,7 +1726,7 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
continue;
// Get the location for the field.
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
+ llvm::DIFile *FieldDefUnit = getOrCreateFile(Field->getLocation());
unsigned FieldLine = getLineNumber(Field->getLocation());
QualType FType = Field->getType();
uint64_t FieldSize = 0;
@@ -1755,11 +1759,11 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
unsigned Flags = 0;
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
- Flags = llvm::DIDescriptor::FlagProtected;
+ Flags = llvm::DINode::FlagProtected;
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
- Flags = llvm::DIDescriptor::FlagPrivate;
+ Flags = llvm::DINode::FlagPrivate;
else if (Field->getAccessControl() == ObjCIvarDecl::Public)
- Flags = llvm::DIDescriptor::FlagPublic;
+ Flags = llvm::DINode::FlagPublic;
llvm::MDNode *PropertyNode = nullptr;
if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
@@ -1767,7 +1771,7 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
SourceLocation Loc = PD->getLocation();
- llvm::DIFile PUnit = getOrCreateFile(Loc);
+ llvm::DIFile *PUnit = getOrCreateFile(Loc);
unsigned PLine = getLineNumber(Loc);
ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
@@ -1788,15 +1792,16 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
EltTys.push_back(FieldTy);
}
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
DBuilder.replaceArrays(RealDecl, Elements);
LexicalBlockStack.pop_back();
return RealDecl;
}
-llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
- llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
+llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
+ llvm::DIFile *Unit) {
+ llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
int64_t Count = Ty->getNumElements();
if (Count == 0)
// If number of elements are not known then this is an unbounded array.
@@ -1804,7 +1809,7 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
Count = -1;
llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(0, Count);
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
+ llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
@@ -1812,7 +1817,7 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
-llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
uint64_t Size;
uint64_t Align;
@@ -1858,32 +1863,33 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile Unit) {
EltTy = Ty->getElementType();
}
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
+ llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
- llvm::DIType DbgTy = DBuilder.createArrayType(
- Size, Align, getOrCreateType(EltTy, Unit), SubscriptArray);
- return DbgTy;
+ return DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ SubscriptArray);
}
-llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+ llvm::DIFile *Unit) {
return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, Ty,
Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
- llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
+ llvm::DIFile *Unit) {
return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, Ty,
Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
- llvm::DIFile U) {
- llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
- if (!Ty->getPointeeType()->isFunctionType())
+llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
+ llvm::DIFile *U) {
+ uint64_t Size = CGM.getCXXABI().isTypeInfoCalculable(QualType(Ty, 0))
+ ? CGM.getContext().getTypeSize(Ty)
+ : 0;
+ llvm::DIType *ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
+ if (Ty->isMemberDataPointerType())
return DBuilder.createMemberPointerType(
- getOrCreateType(Ty->getPointeeType(), U), ClassType,
- CGM.getContext().getTypeSize(Ty));
+ getOrCreateType(Ty->getPointeeType(), U), ClassType, Size);
const FunctionProtoType *FPT =
Ty->getPointeeType()->getAs<FunctionProtoType>();
@@ -1891,17 +1897,16 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
getOrCreateInstanceMethodType(CGM.getContext().getPointerType(QualType(
Ty->getClass(), FPT->getTypeQuals())),
FPT, U),
- ClassType, CGM.getContext().getTypeSize(Ty));
+ ClassType, Size);
}
-llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile U) {
+llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
// Ignore the atomic wrapping
// FIXME: What is the correct representation?
return getOrCreateType(Ty->getValueType(), U);
}
-/// CreateEnumType - get enumeration type.
-llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) {
+llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
uint64_t Align = 0;
@@ -1915,14 +1920,14 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) {
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!ED->getDefinition()) {
- llvm::DIDescriptor EDContext;
- EDContext = getContextDescriptor(cast<Decl>(ED->getDeclContext()));
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ llvm::DIScope *EDContext =
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
StringRef EDName = ED->getName();
- llvm::DIType RetTy = DBuilder.createReplaceableForwardDecl(
+ llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType(
llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
- 0, Size, Align, FullName);
+ 0, Size, Align, llvm::DINode::FlagFwdDecl, FullName);
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -1932,7 +1937,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) {
return CreateTypeDefinition(Ty);
}
-llvm::DIType CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
+llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
uint64_t Align = 0;
@@ -1943,7 +1948,7 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- // Create DIEnumerator elements for each enumerator.
+ // Create elements for each enumerator.
SmallVector<llvm::Metadata *, 16> Enumerators;
ED = ED->getDefinition();
for (const auto *Enum : ED->enumerators()) {
@@ -1952,19 +1957,17 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
}
// Return a CompositeType for the enum itself.
- llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators);
+ llvm::DINodeArray EltArray = DBuilder.getOrCreateArray(Enumerators);
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIDescriptor EnumContext =
+ llvm::DIScope *EnumContext =
getContextDescriptor(cast<Decl>(ED->getDeclContext()));
- llvm::DIType ClassTy = ED->isFixed()
- ? getOrCreateType(ED->getIntegerType(), DefUnit)
- : llvm::DIType();
- llvm::DIType DbgTy =
- DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
- Size, Align, EltArray, ClassTy, FullName);
- return DbgTy;
+ llvm::DIType *ClassTy =
+ ED->isFixed() ? getOrCreateType(ED->getIntegerType(), DefUnit) : nullptr;
+ return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
+ Line, Size, Align, EltArray, ClassTy,
+ FullName);
}
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
@@ -2022,9 +2025,7 @@ 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) {
+llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
@@ -2033,10 +2034,10 @@ llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
if (it != TypeCache.end()) {
// Verify that the debug info still exists.
if (llvm::Metadata *V = it->second)
- return llvm::DIType(cast<llvm::MDNode>(V));
+ return cast<llvm::DIType>(V);
}
- return llvm::DIType();
+ return nullptr;
}
void CGDebugInfo::completeTemplateDefinition(
@@ -2050,20 +2051,18 @@ 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) {
+llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
if (Ty.isNull())
- return llvm::DIType();
+ return nullptr;
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- if (llvm::DIType T = getTypeOrNull(Ty))
+ if (auto *T = getTypeOrNull(Ty))
return T;
// Otherwise create the type.
- llvm::DIType Res = CreateTypeNode(Ty, Unit);
+ llvm::DIType *Res = CreateTypeNode(Ty, Unit);
void *TyPtr = Ty.getAsOpaquePtr();
// And update the type cache.
@@ -2072,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
@@ -2098,8 +2095,7 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
}
}
-/// CreateTypeNode - Create a new debug type node.
-llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
+llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
return CreateQualifiedType(Ty, Unit);
@@ -2179,27 +2175,25 @@ 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) {
+llvm::DIType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
+ llvm::DIFile *Unit) {
QualType QTy(Ty, 0);
- llvm::DICompositeType T(getTypeOrNull(QTy));
+ auto *T = cast_or_null<llvm::DICompositeTypeBase>(getTypeOrNull(QTy));
// We may have cached a forward decl when we could have created
// a non-forward decl. Go ahead and create a non-forward decl
// now.
- if (T && !T.isForwardDecl())
+ if (T && !T->isForwardDecl())
return T;
// Otherwise create the type.
- llvm::DICompositeType Res = CreateLimitedType(Ty);
+ llvm::DICompositeType *Res = CreateLimitedType(Ty);
// Propagate members from the declaration to the definition
// CreateType(const RecordType*) will overwrite this with the members in the
// correct order if the full type is needed.
- DBuilder.replaceArrays(Res, T.getElements());
+ DBuilder.replaceArrays(Res, T ? T->getElements() : llvm::DINodeArray());
// And update the type cache.
TypeCache[QTy.getAsOpaquePtr()].reset(Res);
@@ -2207,21 +2201,22 @@ llvm::DIType CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
}
// TODO: Currently used for context chains when limiting debug info.
-llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
// Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- llvm::DIDescriptor RDContext =
+ llvm::DIScope *RDContext =
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
// If we ended up creating the type during the context chain construction,
// just return that.
- llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
- if (T && (!T.isForwardDecl() || !RD->getDefinition()))
+ auto *T = cast_or_null<llvm::DICompositeType>(
+ getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ if (T && (!T->isForwardDecl() || !RD->getDefinition()))
return T;
// If this is just a forward or incomplete declaration, construct an
@@ -2232,38 +2227,27 @@ llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- llvm::DICompositeType RealDecl;
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
- if (RD->isUnion())
- RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, Size,
- Align, 0, llvm::DIArray(), 0, FullName);
- else if (RD->isClass()) {
- // FIXME: This could be a struct type giving a default visibility different
- // than C++ class type, but needs llvm metadata changes first.
- RealDecl = DBuilder.createClassType(
- RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(),
- llvm::DIArray(), llvm::DIType(), llvm::DIArray(), FullName);
- } else
- RealDecl = DBuilder.createStructType(
- RDContext, RDName, DefUnit, Line, Size, Align, 0, llvm::DIType(),
- llvm::DIArray(), 0, llvm::DIType(), FullName);
+ llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
+ getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0,
+ FullName);
RegionMap[Ty->getDecl()].reset(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
if (const ClassTemplateSpecializationDecl *TSpecial =
dyn_cast<ClassTemplateSpecializationDecl>(RD))
- DBuilder.replaceArrays(RealDecl, llvm::DIArray(),
+ DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(),
CollectCXXTemplateParams(TSpecial, DefUnit));
return RealDecl;
}
void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
- llvm::DICompositeType RealDecl) {
+ llvm::DICompositeType *RealDecl) {
// A class's primary base or the class itself contains the vtable.
- llvm::DICompositeType ContainingType;
+ llvm::DICompositeType *ContainingType = nullptr;
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
// Seek non-virtual primary base root.
@@ -2275,7 +2259,7 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
else
break;
}
- ContainingType = llvm::DICompositeType(
+ ContainingType = cast<llvm::DICompositeType>(
getOrCreateType(QualType(PBase->getTypeForDecl(), 0),
getOrCreateFile(RD->getLocation())));
} else if (RD->isDynamicClass())
@@ -2284,30 +2268,29 @@ 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);
+llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
+ StringRef Name, uint64_t *Offset) {
+ llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize,
- FieldAlign, *Offset, 0, FieldTy);
+ llvm::DIType *Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize,
+ FieldAlign, *Offset, 0, FieldTy);
*Offset += FieldSize;
return Ty;
}
-void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD,
- llvm::DIFile Unit,
- StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &FDContext,
- llvm::DIArray &TParamsArray,
+void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
+ StringRef &Name,
+ StringRef &LinkageName,
+ llvm::DIScope *&FDContext,
+ llvm::DINodeArray &TParamsArray,
unsigned &Flags) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
Name = getFunctionName(FD);
// Use mangled name as linkage name for C/C++ functions.
if (FD->hasPrototype()) {
LinkageName = CGM.getMangledName(GD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DINode::FlagPrototyped;
}
// No need to replicate the linkage name if it isn't different from the
// subprogram name, no need to have it at all unless coverage is enabled or
@@ -2330,10 +2313,10 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD,
}
}
-void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
+void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
unsigned &LineNo, QualType &T,
StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &VDContext) {
+ llvm::DIScope *&VDContext) {
Unit = getOrCreateFile(VD->getLocation());
LineNo = getLineNumber(VD->getLocation());
@@ -2362,19 +2345,27 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
// FIXME: Generalize this for even non-member global variables where the
// declaration and definition may have different lexical decl contexts, once
// we have support for emitting declarations of (non-member) global variables.
- VDContext = getContextDescriptor(
- dyn_cast<Decl>(VD->isStaticDataMember() ? VD->getLexicalDeclContext()
- : VD->getDeclContext()));
-}
-
-llvm::DISubprogram
+ const DeclContext *DC = VD->isStaticDataMember() ? VD->getLexicalDeclContext()
+ : VD->getDeclContext();
+ // When a record type contains an in-line initialization of a static data
+ // member, and the record type is marked as __declspec(dllexport), an implicit
+ // definition of the member will be created in the record context. DWARF
+ // doesn't seem to have a nice way to describe this in a form that consumers
+ // are likely to understand, so fake the "normal" situation of a definition
+ // outside the class by putting it in the global scope.
+ if (DC->isRecord())
+ DC = CGM.getContext().getTranslationUnitDecl();
+ VDContext = getContextDescriptor(dyn_cast<Decl>(DC));
+}
+
+llvm::DISubprogram *
CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
- llvm::DIArray TParamsArray;
+ llvm::DINodeArray TParamsArray;
StringRef Name, LinkageName;
unsigned Flags = 0;
SourceLocation Loc = FD->getLocation();
- llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor DContext(Unit);
+ llvm::DIFile *Unit = getOrCreateFile(Loc);
+ llvm::DIScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
collectFunctionDeclProps(FD, Unit, Name, LinkageName, DContext,
@@ -2386,35 +2377,31 @@ CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
QualType FnType =
CGM.getContext().getFunctionType(FD->getReturnType(), ArgTypes,
FunctionProtoType::ExtProtoInfo());
- llvm::DISubprogram SP =
- DBuilder.createTempFunctionFwdDecl(DContext, Name, LinkageName, Unit, Line,
- getOrCreateFunctionType(FD, FnType, Unit),
- !FD->isExternallyVisible(),
- false /*declaration*/, 0, Flags,
- CGM.getLangOpts().Optimize, nullptr,
- TParamsArray, getFunctionDeclaration(FD));
+ llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl(
+ DContext, Name, LinkageName, Unit, Line,
+ getOrCreateFunctionType(FD, FnType, Unit), !FD->isExternallyVisible(),
+ false /*declaration*/, 0, Flags, CGM.getLangOpts().Optimize, nullptr,
+ TParamsArray.get(), getFunctionDeclaration(FD));
const FunctionDecl *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
- FwdDeclReplaceMap.emplace_back(
- std::piecewise_construct, std::make_tuple(CanonDecl),
- std::make_tuple(static_cast<llvm::Metadata *>(SP)));
+ FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
+ std::make_tuple(CanonDecl),
+ std::make_tuple(SP));
return SP;
}
-llvm::DIGlobalVariable
+llvm::DIGlobalVariable *
CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
QualType T;
StringRef Name, LinkageName;
SourceLocation Loc = VD->getLocation();
- llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor DContext(Unit);
+ llvm::DIFile *Unit = getOrCreateFile(Loc);
+ llvm::DIScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
- llvm::DIGlobalVariable GV =
- DBuilder.createTempGlobalVariableFwdDecl(DContext, Name, LinkageName, Unit,
- Line, getOrCreateType(T, Unit),
- !VD->isExternallyVisible(),
- nullptr, nullptr);
+ auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
+ DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
+ !VD->isExternallyVisible(), nullptr, nullptr);
FwdDeclReplaceMap.emplace_back(
std::piecewise_construct,
std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
@@ -2422,7 +2409,7 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
return GV;
}
-llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
+llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
// We only need a declaration (not a definition) of the type - so use whatever
// we would otherwise do to get a type for a pointee. (forward declarations in
// limited debug info, full definitions (if the type definition is available)
@@ -2433,7 +2420,7 @@ llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
auto I = DeclCache.find(D->getCanonicalDecl());
if (I != DeclCache.end())
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(I->second));
+ return dyn_cast_or_null<llvm::DINode>(I->second);
// No definition for now. Emit a forward definition that might be
// merged with a potential upcoming definition.
@@ -2442,59 +2429,53 @@ llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
else if (const auto *VD = dyn_cast<VarDecl>(D))
return getGlobalVariableForwardDeclaration(VD);
- return llvm::DIDescriptor();
+ return nullptr;
}
-/// getFunctionDeclaration - Return debug info descriptor to describe method
-/// declaration for the given method definition.
-llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
+llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
- return llvm::DISubprogram();
+ return nullptr;
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
- return llvm::DISubprogram();
+ return nullptr;
// Setup context.
- llvm::DIScope S = getContextDescriptor(cast<Decl>(D->getDeclContext()));
+ auto *S = getContextDescriptor(cast<Decl>(D->getDeclContext()));
auto MI = SPCache.find(FD->getCanonicalDecl());
if (MI == SPCache.end()) {
if (const CXXMethodDecl *MD =
dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
- llvm::DICompositeType T(S);
- llvm::DISubprogram SP =
- CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
- return SP;
+ return CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()),
+ cast<llvm::DICompositeType>(S));
}
}
if (MI != SPCache.end()) {
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(MI->second));
- if (SP.isSubprogram() && !SP.isDefinition())
+ auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second);
+ if (SP && !SP->isDefinition())
return SP;
}
for (auto NextFD : FD->redecls()) {
auto MI = SPCache.find(NextFD->getCanonicalDecl());
if (MI != SPCache.end()) {
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(MI->second));
- if (SP.isSubprogram() && !SP.isDefinition())
+ auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second);
+ if (SP && !SP->isDefinition())
return SP;
}
}
- return llvm::DISubprogram();
+ return nullptr;
}
-// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
+// getOrCreateFunctionType - Construct type. If it is a c++ method, include
// implicit parameter "this".
-llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
- QualType FnType,
- llvm::DIFile F) {
+llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
+ QualType FnType,
+ llvm::DIFile *F) {
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
- // Create fake but valid subroutine type. Otherwise
- // llvm::DISubprogram::Verify() would return false, and
- // subprogram DIE will miss DW_AT_decl_file and
- // DW_AT_decl_line fields.
+ // Create fake but valid subroutine type. Otherwise -verify would fail, and
+ // subprogram DIE will miss DW_AT_decl_file and DW_AT_decl_line fields.
return DBuilder.createSubroutineType(F,
DBuilder.getOrCreateTypeArray(None));
@@ -2515,11 +2496,10 @@ llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
Elts.push_back(getOrCreateType(ResultTy, F));
// "self" pointer is always first argument.
QualType SelfDeclTy = OMethod->getSelfDecl()->getType();
- llvm::DIType SelfTy = getOrCreateType(SelfDeclTy, F);
- Elts.push_back(CreateSelfType(SelfDeclTy, SelfTy));
+ Elts.push_back(CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
// "_cmd" pointer is always second argument.
- llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
- Elts.push_back(DBuilder.createArtificialType(CmdTy));
+ Elts.push_back(DBuilder.createArtificialType(
+ getOrCreateType(OMethod->getCmdDecl()->getType(), F)));
// Get rest of the arguments.
for (const auto *PI : OMethod->params())
Elts.push_back(getOrCreateType(PI->getType(), F));
@@ -2527,7 +2507,7 @@ llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
if (OMethod->isVariadic())
Elts.push_back(DBuilder.createUnspecifiedParameter());
- llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
+ llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
return DBuilder.createSubroutineType(F, EltTypeArray);
}
@@ -2541,14 +2521,13 @@ llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
for (unsigned i = 0, e = FPT->getNumParams(); i != e; ++i)
EltTys.push_back(getOrCreateType(FPT->getParamType(i), F));
EltTys.push_back(DBuilder.createUnspecifiedParameter());
- llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
+ llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
return DBuilder.createSubroutineType(F, EltTypeArray);
}
- return llvm::DICompositeType(getOrCreateType(FnType, F));
+ 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) {
@@ -2562,20 +2541,19 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
bool HasDecl = (D != nullptr);
unsigned Flags = 0;
- llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor FDContext(Unit);
- llvm::DIArray TParamsArray;
+ llvm::DIFile *Unit = getOrCreateFile(Loc);
+ llvm::DIScope *FDContext = Unit;
+ llvm::DINodeArray TParamsArray;
if (!HasDecl) {
// Use llvm function name.
LinkageName = Fn->getName();
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // If there is a DISubprogram for this function available then use it.
+ // If there is a subprogram for this function available then use it.
auto FI = SPCache.find(FD->getCanonicalDecl());
if (FI != SPCache.end()) {
- llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
- if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
- llvm::MDNode *SPN = SP;
- LexicalBlockStack.emplace_back(SPN);
+ auto *SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second);
+ if (SP && SP->isDefinition()) {
+ LexicalBlockStack.emplace_back(SP);
RegionMap[D].reset(SP);
return;
}
@@ -2584,17 +2562,17 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
TParamsArray, Flags);
} else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
Name = getObjCMethodName(OMD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DINode::FlagPrototyped;
} else {
// Use llvm function name.
Name = Fn->getName();
- Flags |= llvm::DIDescriptor::FlagPrototyped;
+ Flags |= llvm::DINode::FlagPrototyped;
}
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
if (!HasDecl || D->isImplicit()) {
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DINode::FlagArtificial;
// Artificial functions without a location should not silently reuse CurLoc.
if (Loc.isInvalid())
CurLoc = SourceLocation();
@@ -2607,11 +2585,11 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
// FunctionDecls. When/if we fix this we can have FDContext be TheCU/null for
// all subprograms instead of the actual context since subprogram definitions
// are emitted as CU level entities by the backend.
- llvm::DISubprogram SP = DBuilder.createFunction(
+ llvm::DISubprogram *SP = DBuilder.createFunction(
FDContext, Name, LinkageName, Unit, LineNo,
getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(),
true /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize, Fn,
- TParamsArray, getFunctionDeclaration(D));
+ TParamsArray.get(), getFunctionDeclaration(D));
// We might get here with a VarDecl in the case we're generating
// code for the initialization of globals. Do not record these decls
// as they will overwrite the actual VarDecl Decl in the cache.
@@ -2619,18 +2597,13 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
DeclCache[D->getCanonicalDecl()].reset(static_cast<llvm::Metadata *>(SP));
// Push the function onto the lexical block stack.
- llvm::MDNode *SPN = SP;
- LexicalBlockStack.emplace_back(SPN);
+ LexicalBlockStack.emplace_back(SP);
if (HasDecl)
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,
- bool ForceColumnInfo) {
+void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
// Update our current location
setLocation(Loc);
@@ -2639,24 +2612,18 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
llvm::MDNode *Scope = LexicalBlockStack.back();
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(
- getLineNumber(CurLoc), getColumnNumber(CurLoc, ForceColumnInfo), Scope));
+ 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())
Back = LexicalBlockStack.back().get();
- llvm::DIDescriptor D = DBuilder.createLexicalBlock(
- llvm::DIDescriptor(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc),
- getColumnNumber(CurLoc));
- llvm::MDNode *DN = D;
- LexicalBlockStack.emplace_back(DN);
+ LexicalBlockStack.emplace_back(DBuilder.createLexicalBlock(
+ cast<llvm::DIScope>(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc),
+ 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.
@@ -2673,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!");
@@ -2688,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();
@@ -2703,17 +2667,15 @@ 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) {
+llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *XOffset) {
SmallVector<llvm::Metadata *, 5> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
unsigned FieldAlign;
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
QualType Type = VD->getType();
FieldOffset = 0;
@@ -2760,7 +2722,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
}
FType = Type;
- llvm::DIType FieldTy = getOrCreateType(FType, Unit);
+ llvm::DIType *FieldTy = getOrCreateType(FType, Unit);
FieldSize = CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().toBits(Align);
@@ -2770,16 +2732,15 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
- unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
+ unsigned Flags = llvm::DINode::FlagBlockByrefStruct;
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
- llvm::DIType(), Elements);
+ nullptr, Elements);
}
-/// EmitDeclare - Emit local variable declaration debug info.
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::LLVMConstants Tag,
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
llvm::Value *Storage, unsigned ArgNo,
CGBuilderTy &Builder) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -2788,10 +2749,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::LLVMConstants Tag,
bool Unwritten =
VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
cast<Decl>(VD->getDeclContext())->isImplicit());
- llvm::DIFile Unit;
+ llvm::DIFile *Unit = nullptr;
if (!Unwritten)
Unit = getOrCreateFile(VD->getLocation());
- llvm::DIType Ty;
+ llvm::DIType *Ty;
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
@@ -2810,58 +2771,64 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::LLVMConstants Tag,
Line = getLineNumber(VD->getLocation());
Column = getColumnNumber(VD->getLocation());
}
+ SmallVector<int64_t, 9> Expr;
unsigned Flags = 0;
if (VD->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
+ Flags |= llvm::DINode::FlagArtificial;
// If this is the first argument and it is implicit then
// give it an object pointer flag.
// FIXME: There has to be a better way to do this, but for static
// functions there won't be an implicit param at arg1 and
// otherwise it is 'self' or 'this'.
if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
- Flags |= llvm::DIDescriptor::FlagObjectPointer;
+ Flags |= llvm::DINode::FlagObjectPointer;
if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage))
if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
!VD->getType()->isPointerType())
- Flags |= llvm::DIDescriptor::FlagIndirectVariable;
+ Expr.push_back(llvm::dwarf::DW_OP_deref);
- llvm::MDNode *Scope = LexicalBlockStack.back();
+ auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
StringRef Name = VD->getName();
if (!Name.empty()) {
if (VD->hasAttr<BlocksAttr>()) {
CharUnits offset = CharUnits::fromQuantity(32);
- SmallVector<int64_t, 9> addr;
- addr.push_back(llvm::dwarf::DW_OP_plus);
+ Expr.push_back(llvm::dwarf::DW_OP_plus);
// offset of __forwarding field
offset = CGM.getContext().toCharUnitsFromBits(
CGM.getTarget().getPointerWidth(0));
- addr.push_back(offset.getQuantity());
- addr.push_back(llvm::dwarf::DW_OP_deref);
- addr.push_back(llvm::dwarf::DW_OP_plus);
+ Expr.push_back(offset.getQuantity());
+ Expr.push_back(llvm::dwarf::DW_OP_deref);
+ Expr.push_back(llvm::dwarf::DW_OP_plus);
// offset of x field
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
- addr.push_back(offset.getQuantity());
+ Expr.push_back(offset.getQuantity());
// Create the descriptor for the variable.
- llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), VD->getName(), Unit, Line, Ty, ArgNo);
+ auto *D = DBuilder.createLocalVariable(Tag, Scope, VD->getName(), Unit,
+ Line, Ty, ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr),
- Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
return;
} else if (isa<VariableArrayType>(VD->getType()))
- Flags |= llvm::DIDescriptor::FlagIndirectVariable;
+ Expr.push_back(llvm::dwarf::DW_OP_deref);
} else if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
if (RD->isUnion() && RD->isAnonymousStructOrUnion()) {
+ // GDB has trouble finding local variables in anonymous unions, so we emit
+ // artifical local variables for each of the members.
+ //
+ // FIXME: Remove this code as soon as GDB supports this.
+ // The debug info verifier in LLVM operates based on the assumption that a
+ // variable has the same size as its storage and we had to disable the check
+ // for artificial variables.
for (const auto *Field : RD->fields()) {
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
StringRef FieldName = Field->getName();
// Ignore unnamed fields. Do not ignore unnamed records.
@@ -2869,28 +2836,28 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::LLVMConstants Tag,
continue;
// Use VarDecl's Tag, Scope and Line number.
- llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), FieldName, Unit, Line, FieldTy,
- CGM.getLangOpts().Optimize, Flags, ArgNo);
+ auto *D = DBuilder.createLocalVariable(
+ Tag, Scope, FieldName, Unit, Line, FieldTy,
+ CGM.getLangOpts().Optimize, Flags | llvm::DINode::FlagArtificial,
+ ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = DBuilder.insertDeclare(
- Storage, D, DBuilder.createExpression(), Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
}
- return;
}
}
// Create the descriptor for the variable.
- llvm::DIVariable D = DBuilder.createLocalVariable(
- Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, ArgNo);
+ auto *D =
+ DBuilder.createLocalVariable(Tag, Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags, ArgNo);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = DBuilder.insertDeclare(
- Storage, D, DBuilder.createExpression(), Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
+ llvm::DebugLoc::get(Line, Column, Scope),
+ Builder.GetInsertBlock());
}
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
@@ -2900,15 +2867,9 @@ 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);
+llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
+ llvm::DIType *Ty) {
+ llvm::DIType *CachedTy = getTypeOrNull(QualTy);
if (CachedTy)
Ty = CachedTy;
return DBuilder.createObjectPointerType(Ty);
@@ -2926,8 +2887,8 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
bool isByRef = VD->hasAttr<BlocksAttr>();
uint64_t XOffset = 0;
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- llvm::DIType Ty;
+ llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIType *Ty;
if (isByRef)
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
else
@@ -2968,23 +2929,21 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
}
// Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_auto_variable,
- llvm::DIDescriptor(LexicalBlockStack.back()),
- VD->getName(), Unit, Line, Ty);
+ auto *D = DBuilder.createLocalVariable(
+ llvm::dwarf::DW_TAG_auto_variable,
+ cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
+ Line, Ty);
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call = InsertPoint ?
- DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr),
- InsertPoint)
- : DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr),
- Builder.GetInsertBlock());
- Call->setDebugLoc(
- llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back()));
+ auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back());
+ if (InsertPoint)
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
+ InsertPoint);
+ else
+ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
+ 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) {
@@ -3013,7 +2972,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Collect some general information about the block's location.
SourceLocation loc = blockDecl->getCaretLocation();
- llvm::DIFile tunit = getOrCreateFile(loc);
+ llvm::DIFile *tunit = getOrCreateFile(loc);
unsigned line = getLineNumber(loc);
unsigned column = getColumnNumber(loc);
@@ -3096,7 +3055,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
const VarDecl *variable = capture->getVariable();
StringRef name = variable->getName();
- llvm::DIType fieldType;
+ llvm::DIType *fieldType;
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
@@ -3118,70 +3077,62 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::raw_svector_ostream(typeName) << "__block_literal_"
<< CGM.getUniqueBlockCount();
- llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields);
+ llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields);
- llvm::DIType type =
- DBuilder.createStructType(tunit, typeName.str(), tunit, line,
- CGM.getContext().toBits(block.BlockSize),
- CGM.getContext().toBits(block.BlockAlign), 0,
- llvm::DIType(), fieldsArray);
+ llvm::DIType *type = DBuilder.createStructType(
+ tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize),
+ CGM.getContext().toBits(block.BlockAlign), 0, nullptr, fieldsArray);
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
// Get overall information about the block.
- unsigned flags = llvm::DIDescriptor::FlagArtificial;
- llvm::MDNode *scope = LexicalBlockStack.back();
+ unsigned flags = llvm::DINode::FlagArtificial;
+ auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back());
// Create the descriptor for the parameter.
- llvm::DIVariable debugVar = DBuilder.createLocalVariable(
- llvm::dwarf::DW_TAG_arg_variable, llvm::DIDescriptor(scope),
- Arg->getName(), tunit, line, type, CGM.getLangOpts().Optimize, flags,
- ArgNo);
+ auto *debugVar = DBuilder.createLocalVariable(
+ llvm::dwarf::DW_TAG_arg_variable, scope, Arg->getName(), tunit, line,
+ type, CGM.getLangOpts().Optimize, flags, ArgNo);
if (LocalAddr) {
// Insert an llvm.dbg.value into the current block.
- llvm::Instruction *DbgVal = DBuilder.insertDbgValueIntrinsic(
+ DBuilder.insertDbgValueIntrinsic(
LocalAddr, 0, debugVar, DBuilder.createExpression(),
- Builder.GetInsertBlock());
- DbgVal->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ llvm::DebugLoc::get(line, column, scope), Builder.GetInsertBlock());
}
// Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *DbgDecl = DBuilder.insertDeclare(
- Arg, debugVar, DBuilder.createExpression(), Builder.GetInsertBlock());
- DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(),
+ llvm::DebugLoc::get(line, column, scope),
+ 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
+llvm::DIDerivedType *
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
if (!D->isStaticDataMember())
- return llvm::DIDerivedType();
+ return nullptr;
+
auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
assert(MI->second && "Static data member declaration should still exist");
- return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
+ return cast<llvm::DIDerivedType>(MI->second);
}
// If the member wasn't found in the cache, lazily construct and add it to the
// type (used when a limited form of the type is emitted).
auto DC = D->getDeclContext();
- llvm::DICompositeType Ctxt(getContextDescriptor(cast<Decl>(DC)));
+ auto *Ctxt =
+ cast<llvm::DICompositeType>(getContextDescriptor(cast<Decl>(DC)));
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::DIDescriptor DContext) {
- llvm::DIGlobalVariable GV;
+llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
+ const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
+ StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
+ llvm::DIGlobalVariable *GV = nullptr;
for (const auto *Field : RD->fields()) {
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
StringRef FieldName = Field->getName();
// Ignore unnamed fields, but recurse into anonymous records.
@@ -3193,20 +3144,19 @@ CGDebugInfo::CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile Unit,
continue;
}
// Use VarDecl's Tag, Scope and Line number.
- GV = DBuilder.createGlobalVariable(
- DContext, FieldName, LinkageName, Unit, LineNo, FieldTy,
- Var->hasInternalLinkage(), Var, llvm::DIDerivedType());
+ GV = DBuilder.createGlobalVariable(DContext, FieldName, LinkageName, Unit,
+ LineNo, FieldTy,
+ Var->hasInternalLinkage(), Var, nullptr);
}
return GV;
}
-/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
- llvm::DIFile Unit;
- llvm::DIDescriptor DContext;
+ llvm::DIFile *Unit = nullptr;
+ llvm::DIScope *DContext = nullptr;
unsigned LineNo;
StringRef DeclName, LinkageName;
QualType T;
@@ -3214,7 +3164,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
// Attempt to store one global variable for the declaration - even if we
// emit a lot of fields.
- llvm::DIGlobalVariable GV;
+ llvm::DIGlobalVariable *GV = nullptr;
// If this is an anonymous union then we'll want to emit a global
// variable for each member of the anonymous union so that it's possible
@@ -3233,21 +3183,22 @@ 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);
// Create the descriptor for the variable.
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
- llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
+ llvm::DIType *Ty = getOrCreateType(VD->getType(), Unit);
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
const EnumDecl *ED = cast<EnumDecl>(ECD->getDeclContext());
assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");
Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
}
- // Do not use DIGlobalVariable for enums.
- if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
+ // Do not use global variables for enums.
+ //
+ // FIXME: why not?
+ if (Ty->getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
// Do not emit separate definitions for function local const/statics.
if (isa<FunctionDecl>(VD->getDeclContext()))
@@ -3263,7 +3214,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
return;
}
- llvm::DIDescriptor DContext =
+ llvm::DIScope *DContext =
getContextDescriptor(dyn_cast<Decl>(VD->getDeclContext()));
auto &GV = DeclCache[VD];
@@ -3274,9 +3225,9 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
true, Init, getOrCreateStaticDataMemberDeclarationOrNull(VarD)));
}
-llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
+llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
if (!LexicalBlockStack.empty())
- return llvm::DIScope(LexicalBlockStack.back());
+ return LexicalBlockStack.back();
return getContextDescriptor(D);
}
@@ -3297,21 +3248,30 @@ void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
// Emitting one decl is sufficient - debuggers can detect that this is an
// overloaded name & provide lookup for all the overloads.
const UsingShadowDecl &USD = **UD.shadow_begin();
- if (llvm::DIDescriptor Target =
+ if (llvm::DINode *Target =
getDeclarationOrDefinition(USD.getUnderlyingDecl()))
DBuilder.createImportedDeclaration(
getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target,
getLineNumber(USD.getLocation()));
}
-llvm::DIImportedEntity
+void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
+ auto *Reader = CGM.getContext().getExternalSource();
+ auto Info = Reader->getSourceDescriptor(*ID.getImportedModule());
+ DBuilder.createImportedDeclaration(
+ getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())),
+ getOrCreateModuleRef(Info),
+ getLineNumber(ID.getLocation()));
+}
+
+llvm::DIImportedEntity *
CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
- return llvm::DIImportedEntity(nullptr);
+ return nullptr;
auto &VH = NamespaceAliasCache[&NA];
if (VH)
- return llvm::DIImportedEntity(cast<llvm::MDNode>(VH));
- llvm::DIImportedEntity R(nullptr);
+ return cast<llvm::DIImportedEntity>(VH);
+ llvm::DIImportedEntity *R;
if (const NamespaceAliasDecl *Underlying =
dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
// This could cache & dedup here rather than relying on metadata deduping.
@@ -3328,21 +3288,19 @@ CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
return R;
}
-/// getOrCreateNamesSpace - Return namespace descriptor for the given
-/// namespace decl.
-llvm::DINameSpace
+llvm::DINamespace *
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
NSDecl = NSDecl->getCanonicalDecl();
auto I = NameSpaceCache.find(NSDecl);
if (I != NameSpaceCache.end())
- return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
+ return cast<llvm::DINamespace>(I->second);
unsigned LineNo = getLineNumber(NSDecl->getLocation());
- llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIDescriptor Context =
- getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
- llvm::DINameSpace NS =
- DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ llvm::DIFile *FileD = getOrCreateFile(NSDecl->getLocation());
+ llvm::DIScope *Context =
+ getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
+ llvm::DINamespace *NS =
+ DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl].reset(NS);
return NS;
}
@@ -3352,28 +3310,28 @@ void CGDebugInfo::finalize() {
// element and the size(), so don't cache/reference them.
for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) {
ObjCInterfaceCacheEntry E = ObjCInterfaceCache[i];
- E.Decl.replaceAllUsesWith(CGM.getLLVMContext(),
- E.Type->getDecl()->getDefinition()
- ? CreateTypeDefinition(E.Type, E.Unit)
- : E.Decl);
+ llvm::DIType *Ty = E.Type->getDecl()->getDefinition()
+ ? CreateTypeDefinition(E.Type, E.Unit)
+ : E.Decl;
+ DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
}
for (auto p : ReplaceMap) {
assert(p.second);
- llvm::DIType Ty(cast<llvm::MDNode>(p.second));
- assert(Ty.isForwardDecl());
+ auto *Ty = cast<llvm::DIType>(p.second);
+ assert(Ty->isForwardDecl());
auto it = TypeCache.find(p.first);
assert(it != TypeCache.end());
assert(it->second);
- llvm::DIType RepTy(cast<llvm::MDNode>(it->second));
- Ty.replaceAllUsesWith(CGM.getLLVMContext(), RepTy);
+ DBuilder.replaceTemporary(llvm::TempDIType(Ty),
+ cast<llvm::DIType>(it->second));
}
for (const auto &p : FwdDeclReplaceMap) {
assert(p.second);
- llvm::DIDescriptor FwdDecl(cast<llvm::MDNode>(p.second));
+ llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(p.second));
llvm::Metadata *Repl;
auto it = DeclCache.find(p.first);
@@ -3385,15 +3343,14 @@ void CGDebugInfo::finalize() {
else
Repl = it->second;
- FwdDecl.replaceAllUsesWith(CGM.getLLVMContext(),
- llvm::DIDescriptor(cast<llvm::MDNode>(Repl)));
+ DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
}
// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
RE = RetainedTypes.end(); RI != RE; ++RI)
- DBuilder.retainType(llvm::DIType(cast<llvm::MDNode>(TypeCache[*RI])));
+ DBuilder.retainType(cast<llvm::DIType>(TypeCache[*RI]));
DBuilder.finalize();
}
@@ -3401,7 +3358,8 @@ void CGDebugInfo::finalize() {
void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
return;
- llvm::DIType DieTy = getOrCreateType(Ty, getOrCreateMainFile());
- // Don't ignore in case of explicit cast where it is referenced indirectly.
- DBuilder.retainType(DieTy);
+
+ if (auto *DieTy = getOrCreateType(Ty, getOrCreateMainFile()))
+ // Don't ignore in case of explicit cast where it is referenced indirectly.
+ DBuilder.retainType(DieTy);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 0be032c..4c77a8d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -26,88 +26,92 @@
#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;
-/// CGDebugInfo - 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 ArtificialLocation;
+ friend class ApplyDebugLocation;
friend class SaveAndRestoreLocation;
CodeGenModule &CGM;
const CodeGenOptions::DebugInfoKind DebugKind;
llvm::DIBuilder DBuilder;
- llvm::DICompileUnit TheCU;
+ llvm::DICompileUnit *TheCU = nullptr;
SourceLocation CurLoc;
- llvm::DIType VTablePtrType;
- llvm::DIType ClassTy;
- llvm::DICompositeType ObjTy;
- llvm::DIType SelTy;
- llvm::DIType OCLImage1dDITy, OCLImage1dArrayDITy, OCLImage1dBufferDITy;
- llvm::DIType OCLImage2dDITy, OCLImage2dArrayDITy;
- llvm::DIType OCLImage3dDITy;
- llvm::DIType OCLEventDITy;
- llvm::DIType BlockLiteralGeneric;
-
- /// TypeCache - Cache of previously constructed Types.
+ llvm::DIType *VTablePtrType = nullptr;
+ llvm::DIType *ClassTy = nullptr;
+ llvm::DICompositeType *ObjTy = nullptr;
+ llvm::DIType *SelTy = nullptr;
+ llvm::DIType *OCLImage1dDITy = nullptr;
+ llvm::DIType *OCLImage1dArrayDITy = nullptr;
+ llvm::DIType *OCLImage1dBufferDITy = nullptr;
+ llvm::DIType *OCLImage2dDITy = nullptr;
+ llvm::DIType *OCLImage2dArrayDITy = nullptr;
+ llvm::DIType *OCLImage3dDITy = nullptr;
+ llvm::DIType *OCLEventDITy = nullptr;
+
+ /// Cache of previously constructed Types.
llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache;
struct ObjCInterfaceCacheEntry {
const ObjCInterfaceType *Type;
- llvm::DIType Decl;
- llvm::DIFile Unit;
- ObjCInterfaceCacheEntry(const ObjCInterfaceType *Type, llvm::DIType Decl,
- llvm::DIFile Unit)
+ llvm::DIType *Decl;
+ llvm::DIFile *Unit;
+ ObjCInterfaceCacheEntry(const ObjCInterfaceType *Type, llvm::DIType *Decl,
+ llvm::DIFile *Unit)
: Type(Type), Decl(Decl), Unit(Unit) {}
};
- /// ObjCInterfaceCache - Cache of previously constructed interfaces
- /// which may change.
+ /// Cache of previously constructed interfaces which may change.
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
- /// RetainedTypes - list of interfaces we want to keep even if orphaned.
+ /// Cache of references to AST files such as PCHs or modules.
+ llvm::DenseMap<uint64_t, llvm::DIModule *> ModuleRefCache;
+
+ /// List of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
- /// ReplaceMap - 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.
- std::vector<llvm::TrackingMDNodeRef> LexicalBlockStack;
+ /// 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;
- /// DebugInfoNames - 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;
@@ -116,100 +120,139 @@ 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);
- llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile Fg);
- llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile Fg);
- llvm::DIType CreateType(const TemplateSpecializationType *Ty, llvm::DIFile Fg);
- llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
- llvm::DIFile F);
- 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);
- 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);
- llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
- llvm::DIType CreateTypeDefinition(const ObjCInterfaceType *Ty, llvm::DIFile F);
- 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);
- llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
- 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);
- llvm::DIType CreateEnumType(const EnumType *Ty);
- llvm::DIType CreateTypeDefinition(const EnumType *Ty);
- llvm::DIType CreateSelfType(const QualType &QualTy, llvm::DIType Ty);
- llvm::DIType getTypeOrNull(const QualType);
- llvm::DICompositeType getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile F);
- llvm::DICompositeType getOrCreateInstanceMethodType(
- QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit);
- llvm::DICompositeType getOrCreateFunctionType(const Decl *D, QualType FnType,
- llvm::DIFile F);
- llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
- llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
- llvm::DIType getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile F);
- llvm::DIType CreatePointerLikeType(llvm::dwarf::Tag Tag,
- const Type *Ty, QualType PointeeTy,
- llvm::DIFile F);
+ llvm::DIType *CreateType(const BuiltinType *Ty);
+ llvm::DIType *CreateType(const ComplexType *Ty);
+ llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
+ llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg);
+ llvm::DIType *CreateType(const TemplateSpecializationType *Ty,
+ llvm::DIFile *Fg);
+ llvm::DIType *CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *F);
+ 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);
+ llvm::DIType *CreateType(const LValueReferenceType *Ty, llvm::DIFile *F);
+ 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 *
+ getOrCreateInstanceMethodType(QualType ThisPtr, const FunctionProtoType *Func,
+ 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,
+ QualType PointeeTy, llvm::DIFile *F);
llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty);
- llvm::DIType getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache);
-
- llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
- llvm::DIFile F,
- llvm::DIType RecordTy);
-
- void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, llvm::DIFile F,
+ 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);
+ llvm::DIType *T);
- void CollectCXXBases(const CXXRecordDecl *Decl, llvm::DIFile F,
+ /// 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);
-
- llvm::DIArray
- CollectTemplateParams(const TemplateParameterList *TPList,
- ArrayRef<TemplateArgument> TAList,
- llvm::DIFile Unit);
- llvm::DIArray
- CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit);
- llvm::DIArray
+ 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);
+ llvm::DIFile *F);
- llvm::DIType createFieldType(StringRef name, QualType type,
- uint64_t sizeInBitsOverride, SourceLocation loc,
- AccessSpecifier AS,
- uint64_t offsetInBits,
- llvm::DIFile tunit,
- llvm::DIScope scope,
- const RecordDecl* RD = nullptr);
+ llvm::DIType *createFieldType(StringRef name, QualType type,
+ uint64_t sizeInBitsOverride, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ 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);
- llvm::DIDerivedType CreateRecordStaticField(const VarDecl *Var,
- llvm::DIType RecordTy,
- const RecordDecl* RD);
+ llvm::DIType *RecordTy);
+ llvm::DIDerivedType *CreateRecordStaticField(const VarDecl *Var,
+ llvm::DIType *RecordTy,
+ const RecordDecl *RD);
void CollectRecordNormalField(const FieldDecl *Field, uint64_t OffsetInBits,
- llvm::DIFile F,
+ llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
- llvm::DIType RecordTy, const RecordDecl *RD);
- void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
+ llvm::DIType *RecordTy, const RecordDecl *RD);
+ void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
- llvm::DICompositeType RecordTy);
+ llvm::DICompositeType *RecordTy);
- void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile F,
+ /// 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:
@@ -218,90 +261,85 @@ public:
void finalize();
- /// setLocation - 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);
- /// getLocation - Return the current source location.
- SourceLocation getLocation() const { return CurLoc; }
-
- /// EmitLocation - Emit metadata to indicate a change in line/column
- /// information in the source file.
- /// \param ForceColumnInfo Assume DebugColumnInfo option is true.
- void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
- bool ForceColumnInfo = false);
+ /// 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);
- /// EmitFunctionStart - 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);
- /// EmitFunctionEnd - Constructs the debug code for exiting a function.
+ /// Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder);
- /// EmitLexicalBlockStart - 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);
- /// EmitLexicalBlockEnd - 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);
- /// EmitDeclareOfAutoVariable - 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);
- /// EmitDeclareOfBlockDeclRefVariable - 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);
- /// EmitDeclareOfArgVariable - 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);
- /// EmitDeclareOfBlockLiteralArgVariable - 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);
- /// EmitGlobalVariable - Emit information about a global variable.
+ /// Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
- /// EmitGlobalVariable - 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);
- /// EmitExplicitCastType - 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 C++ namespace alias.
- llvm::DIImportedEntity EmitNamespaceAlias(const NamespaceAliasDecl &NA);
+ /// Emit an @import declaration.
+ void EmitImportDecl(const ImportDecl &ID);
+
+ /// Emit C++ namespace alias.
+ llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA);
- /// getOrCreateRecordType - Emit record type's standalone debug info.
- llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
+ /// Emit record type's standalone debug info.
+ llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L);
- /// getOrCreateInterfaceType - Emit an objective c interface type standalone
- /// debug info.
- llvm::DIType getOrCreateInterfaceType(QualType Ty,
- SourceLocation Loc);
+ /// Emit an Objective-C interface type standalone debug info.
+ llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc);
void completeType(const EnumDecl *ED);
void completeType(const RecordDecl *RD);
@@ -311,133 +349,137 @@ public:
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
private:
- /// EmitDeclare - 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::LLVMConstants Tag,
- llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder);
+ 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.
- llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
- uint64_t *OffSet);
+ /// Build up structure info for the byref. See \a BuildByRefType.
+ llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *OffSet);
- /// getContextDescriptor - Get context info for the decl.
- llvm::DIScope getContextDescriptor(const Decl *Decl);
+ /// Get context info for the decl.
+ llvm::DIScope *getContextDescriptor(const Decl *Decl);
- llvm::DIScope getCurrentContextDescriptor(const Decl *Decl);
+ llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl);
- /// \brief Create a forward decl for a RecordType in a given context.
- llvm::DICompositeType getOrCreateRecordFwdDecl(const RecordType *,
- llvm::DIDescriptor);
+ /// Create a forward decl for a RecordType in a given context.
+ llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *,
+ llvm::DIScope *);
- /// createContextChain - Create a set of decls for the context chain.
- llvm::DIDescriptor createContextChain(const Decl *Decl);
-
- /// getCurrentDirname - Return current directory name.
+ /// Return current directory name.
StringRef getCurrentDirname();
- /// CreateCompileUnit - Create new compile unit.
+ /// Create new compile unit.
void CreateCompileUnit();
- /// getOrCreateFile - Get the file debug info descriptor for the input
- /// location.
- llvm::DIFile getOrCreateFile(SourceLocation Loc);
+ /// Get the file debug info descriptor for the input location.
+ llvm::DIFile *getOrCreateFile(SourceLocation Loc);
- /// getOrCreateMainFile - Get the file info for main compile unit.
- llvm::DIFile getOrCreateMainFile();
+ /// Get the file info for main compile unit.
+ llvm::DIFile *getOrCreateMainFile();
- /// getOrCreateType - Get the type from the cache or create a new type if
- /// necessary.
- llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile Fg);
+ /// Get the type from the cache or create a new type if necessary.
+ llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
- /// getOrCreateLimitedType - Get the type from the cache or create a new
- /// partial type if necessary.
- llvm::DIType getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile F);
+ /// Get a reference to a clang module.
+ llvm::DIModule *
+ getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
+
+ /// Get the type from the cache or create a new partial type if
+ /// necessary.
+ llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F);
- /// CreateTypeNode - Create type metadata for a source language type.
- llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile Fg);
+ /// Create type metadata for a source language type.
+ llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
- /// getObjCInterfaceDecl - 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);
- /// CreateMemberType - Create new member and increase Offset by FType's size.
- llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
- StringRef Name, uint64_t *Offset);
+ /// 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::DIDescriptor getDeclarationOrDefinition(const Decl *D);
+ llvm::DINode *getDeclarationOrDefinition(const Decl *D);
- /// getFunctionDeclaration - 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);
+ 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.
- llvm::DIDerivedType
+ /// \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 DISubprogram describing the forward
- /// decalration represented in the given FunctionDecl.
- llvm::DISubprogram getFunctionForwardDeclaration(const FunctionDecl *FD);
-
- /// \brief Create a DIGlobalVariable 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.
- llvm::DIGlobalVariable
- CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile Unit, unsigned LineNo,
- StringRef LinkageName, llvm::GlobalVariable *Var,
- llvm::DIDescriptor DContext);
-
- /// 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.
+ /// Create a subprogram describing the forward declaration
+ /// represented in the given FunctionDecl.
+ llvm::DISubprogram *getFunctionForwardDeclaration(const FunctionDecl *FD);
+
+ /// Create a global variable describing the forward decalration
+ /// represented in the given VarDecl.
+ llvm::DIGlobalVariable *
+ getGlobalVariableForwardDeclaration(const VarDecl *VD);
+
+ /// \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);
+
+ /// 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);
- /// getObjCMethodName - 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);
- /// getSelectorName - Return selector name. This is used for debugging
+ /// Return selector name. This is used for debugging
/// info.
StringRef getSelectorName(Selector S);
- /// getClassName - Get class name including template argument list.
+ /// Get class name including template argument list.
StringRef getClassName(const RecordDecl *RD);
- /// getVTableName - Get vtable name for the given Class.
+ /// Get the vtable name for the given class.
StringRef getVTableName(const CXXRecordDecl *Decl);
- /// getLineNumber - 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);
- /// getColumnNumber - 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,
+ void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &FDContext,
- llvm::DIArray &TParamsArray,
+ llvm::DIScope *&FDContext,
+ llvm::DINodeArray &TParamsArray,
unsigned &Flags);
- /// \brief Collect various properties of a VarDecl.
- void collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
- unsigned &LineNo, QualType &T,
- StringRef &Name, StringRef &LinkageName,
- llvm::DIDescriptor &VDContext);
+ /// 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);
- /// internString - 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()) {
@@ -448,38 +490,66 @@ private:
}
};
+/// A scoped helper to set the current debug location to the specified
+/// location or preferred location of the specified Expr.
class ApplyDebugLocation {
-protected:
+private:
+ void init(SourceLocation TemporaryLocation, bool DefaultToEmpty = false);
+ ApplyDebugLocation(CodeGenFunction &CGF, bool DefaultToEmpty,
+ SourceLocation TemporaryLocation);
+
llvm::DebugLoc OriginalLocation;
CodeGenFunction &CGF;
public:
- ApplyDebugLocation(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation = SourceLocation(),
- bool ForceColumnInfo = false);
+ /// 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();
-};
-/// ArtificialLocation - An RAII object that temporarily switches to
-/// an artificial debug location that has a valid scope, but no line
-/// information. This is 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.
-///
-/// This is necessary because passing an empty SourceLocation to
-/// CGDebugInfo::setLocation() will result in the last valid location
-/// being reused.
-class ArtificialLocation : public ApplyDebugLocation {
-public:
- ArtificialLocation(CodeGenFunction &CGF);
-};
+ /// \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.
+ 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) {
+ return ApplyDebugLocation(CGF, false, TemporaryLocation);
+ }
+
+ /// 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) {
+ return ApplyDebugLocation(CGF, true, TemporaryLocation);
+ }
+};
} // namespace CodeGen
} // namespace clang
-
#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index 15a1a7f..96aa8c68 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
#include "CodeGenModule.h"
@@ -34,6 +35,7 @@ using namespace CodeGen;
void CodeGenFunction::EmitDecl(const Decl &D) {
switch (D.getKind()) {
case Decl::TranslationUnit:
+ case Decl::ExternCContext:
case Decl::Namespace:
case Decl::UnresolvedUsingTypename:
case Decl::ClassTemplateSpecialization:
@@ -77,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;
@@ -154,6 +157,8 @@ static std::string getStaticDeclName(CodeGenModule &CGM, const VarDecl &D) {
assert(!D.isExternallyVisible() && "name shouldn't matter");
std::string ContextName;
const DeclContext *DC = D.getDeclContext();
+ if (auto *CD = dyn_cast<CapturedDecl>(DC))
+ DC = cast<DeclContext>(CD->getNonClosureContext());
if (const auto *FD = dyn_cast<FunctionDecl>(DC))
ContextName = CGM.getMangledName(FD);
else if (const auto *BD = dyn_cast<BlockDecl>(DC))
@@ -206,6 +211,9 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
setGlobalVisibility(GV, &D);
+ if (supportsCOMDAT() && GV->isWeakForLinker())
+ GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+
if (D.getTLSKind())
setTLSMode(GV, D);
@@ -512,10 +520,7 @@ namespace {
: Addr(addr), Size(size) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy);
- CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(),
- Size, castAddr)
- ->setDoesNotThrow();
+ CGF.EmitLifetimeEnd(Size, Addr);
}
};
}
@@ -575,9 +580,9 @@ static bool isAccessedBy(const VarDecl &var, const Stmt *s) {
}
}
- for (Stmt::const_child_range children = s->children(); children; ++children)
- // children might be null; as in missing decl or conditional of an if-stmt.
- if ((*children) && isAccessedBy(var, *children))
+ for (const Stmt *SubStmt : s->children())
+ // SubStmt might be null; as in missing decl or conditional of an if-stmt.
+ if (SubStmt && isAccessedBy(var, SubStmt))
return true;
return false;
@@ -631,8 +636,9 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
if (capturedByInit) {
// We can use a simple GEP for this because it can't have been
// moved yet.
- tempLV.setAddress(Builder.CreateStructGEP(tempLV.getAddress(),
- getByRefValueLLVMField(cast<VarDecl>(D))));
+ tempLV.setAddress(Builder.CreateStructGEP(
+ nullptr, tempLV.getAddress(),
+ getByRefValueLLVMField(cast<VarDecl>(D)).second));
}
llvm::PointerType *ty
@@ -793,8 +799,9 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- isVolatile, Builder);
+ emitStoresForInitAfterMemset(
+ Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ isVolatile, Builder);
}
return;
}
@@ -807,8 +814,9 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// If necessary, get a pointer to the element and emit it.
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
- emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- isVolatile, Builder);
+ emitStoresForInitAfterMemset(
+ Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
+ isVolatile, Builder);
}
}
@@ -833,21 +841,6 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);
}
-/// Should we use the LLVM lifetime intrinsics for the given local variable?
-static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D,
- unsigned Size) {
- // For now, only in optimized builds.
- if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0)
- return false;
-
- // Limit the size of marked objects to 32 bytes. We don't want to increase
- // compile time by marking tiny objects.
- unsigned SizeThreshold = 32;
-
- return Size > SizeThreshold;
-}
-
-
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
@@ -857,6 +850,35 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
EmitAutoVarCleanups(emission);
}
+/// Emit a lifetime.begin marker if some criteria are satisfied.
+/// \return a pointer to the temporary size Value if a marker was emitted, null
+/// otherwise
+llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
+ llvm::Value *Addr) {
+ // For now, only in optimized builds.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return nullptr;
+
+ // Disable lifetime markers in msan builds.
+ // FIXME: Remove this when msan works with lifetime markers.
+ if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
+ return nullptr;
+
+ llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
+ Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
+ llvm::CallInst *C =
+ Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ C->setDoesNotThrow();
+ return SizeV;
+}
+
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+ Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
+ llvm::CallInst *C =
+ Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ C->setDoesNotThrow();
+}
+
/// EmitAutoVarAlloca - Emit the alloca and debug information for a
/// local variable. Does not emit initialization or destruction.
CodeGenFunction::AutoVarEmission
@@ -952,13 +974,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Emit a lifetime intrinsic if meaningful. There's no point
// in doing this if we don't have a valid insertion point (?).
uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy);
- if (HaveInsertPoint() && shouldUseLifetimeMarkers(*this, D, size)) {
- llvm::Value *sizeV = llvm::ConstantInt::get(Int64Ty, size);
-
- emission.SizeForLifetimeMarkers = sizeV;
- llvm::Value *castAddr = Builder.CreateBitCast(Alloc, Int8PtrTy);
- Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), sizeV, castAddr)
- ->setDoesNotThrow();
+ if (HaveInsertPoint()) {
+ emission.SizeForLifetimeMarkers = EmitLifetimeStart(size, Alloc);
} else {
assert(!emission.useLifetimeMarkers());
}
@@ -1058,8 +1075,8 @@ static bool isCapturedBy(const VarDecl &var, const Expr *e) {
return false;
}
- for (Stmt::const_child_range children = e->children(); children; ++children)
- if (isCapturedBy(var, cast<Expr>(*children)))
+ for (const Stmt *SubStmt : e->children())
+ if (isCapturedBy(var, cast<Expr>(SubStmt)))
return true;
return false;
@@ -1087,7 +1104,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (emission.wasEmittedAsGlobal()) return;
const VarDecl &D = *emission.Variable;
- ApplyDebugLocation DL(*this, D.getLocation());
+ auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation());
QualType type = D.getType();
// If this local has an initializer, emit it now.
@@ -1304,6 +1321,8 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
EHStack.pushCleanup<CallLifetimeEnd>(NormalCleanup,
emission.getAllocatedAddress(),
emission.getSizeForLifetimeMarkers());
+ EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
+ cleanup.setLifetimeMarker();
}
// Check the type for a cleanup.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
index 19e4bdd..00d6d5c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -139,9 +139,32 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
const Expr *Init = D.getInit();
QualType T = D.getType();
+ // The address space of a static local variable (DeclPtr) may be different
+ // from the address space of the "this" argument of the constructor. In that
+ // case, we need an addrspacecast before calling the constructor.
+ //
+ // struct StructWithCtor {
+ // __device__ StructWithCtor() {...}
+ // };
+ // __device__ void foo() {
+ // __shared__ StructWithCtor s;
+ // ...
+ // }
+ //
+ // For example, in the above CUDA code, the static local variable s has a
+ // "shared" address space qualifier, but the constructor of StructWithCtor
+ // expects "this" in the "generic" address space.
+ unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T);
+ unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace();
+ if (ActualAddrSpace != ExpectedAddrSpace) {
+ llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T);
+ llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace);
+ DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);
+ }
+
if (!T->isReferenceType()) {
if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
- (void)CGM.getOpenMPRuntime().EmitOMPThreadPrivateVarDefinition(
+ (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
&D, DeclPtr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
PerformInit, this);
if (PerformInit)
@@ -236,18 +259,23 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
Fn->setSection(Section);
}
+ SetLLVMFunctionAttributes(nullptr, getTypes().arrangeNullaryFunction(), Fn);
+
Fn->setCallingConv(getRuntimeCC());
if (!getLangOpts().Exceptions)
Fn->setDoesNotThrow();
if (!isInSanitizerBlacklist(Fn, Loc)) {
- if (getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+ if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack))
+ Fn->addFnAttr(llvm::Attribute::SafeStack);
}
return Fn;
@@ -267,15 +295,7 @@ void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,
addUsedGlobal(PtrArray);
// If the GV is already in a comdat group, then we have to join it.
- llvm::Comdat *C = GV->getComdat();
-
- // LinkOnce and Weak linkage are lowered down to a single-member comdat group.
- // Make an explicit group so we can join it.
- if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) {
- C = TheModule.getOrInsertComdat(GV->getName());
- GV->setComdat(C);
- }
- if (C)
+ if (llvm::Comdat *C = GV->getComdat())
PtrArray->setComdat(C);
}
@@ -283,6 +303,11 @@ void
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit) {
+ // Check if we've already initialized this decl.
+ auto I = DelayedCXXInitPosition.find(D);
+ if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
+ return;
+
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
SmallString<256> FnName;
{
@@ -312,11 +337,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
CXXThreadLocalInitVars.push_back(Addr);
} else if (PerformInit && ISA) {
EmitPointerToInitFunc(D, Addr, Fn, ISA);
- DelayedCXXInitPosition.erase(D);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
- DelayedCXXInitPosition.erase(D);
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
// C++ [basic.start.init]p2:
// Definitions of explicitly specialized class template static data
@@ -331,24 +354,24 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
// minor startup time optimization. In the MS C++ ABI, there are no guard
// variables, so this COMDAT key is required for correctness.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else if (D->hasAttr<SelectAnyAttr>()) {
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else {
- llvm::DenseMap<const Decl *, unsigned>::iterator I =
- DelayedCXXInitPosition.find(D);
+ I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
if (I == DelayedCXXInitPosition.end()) {
CXXGlobalInits.push_back(Fn);
- } else {
- assert(CXXGlobalInits[I->second] == nullptr);
+ } else if (I->second != ~0U) {
+ assert(I->second < CXXGlobalInits.size() &&
+ CXXGlobalInits[I->second] == nullptr);
CXXGlobalInits[I->second] = Fn;
- DelayedCXXInitPosition.erase(I);
}
}
+
+ // Remember that we already emitted the initializer for this global.
+ DelayedCXXInitPosition[D] = ~0U;
}
void CodeGenModule::EmitCXXThreadLocalInitFunc() {
@@ -401,6 +424,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
AddGlobalCtor(Fn, Priority);
}
+ PrioritizedCXXGlobalInits.clear();
}
SmallString<128> FileName;
@@ -411,7 +435,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
// priority emitted above.
FileName = llvm::sys::path::filename(MainFile->getName());
} else {
- FileName = SmallString<128>("<null>");
+ FileName = "<null>";
}
for (size_t i = 0; i < FileName.size(); ++i) {
@@ -428,7 +452,6 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
AddGlobalCtor(Fn);
CXXGlobalInits.clear();
- PrioritizedCXXGlobalInits.clear();
}
void CodeGenModule::EmitCXXGlobalDtorFunc() {
@@ -477,11 +500,11 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> Decls,
llvm::GlobalVariable *Guard) {
{
- ApplyDebugLocation NL(*this);
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(), FunctionArgList());
// Emit an artificial location for this function.
- ArtificialLocation AL(*this);
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::BasicBlock *ExitBlock = nullptr;
if (Guard) {
@@ -528,11 +551,11 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
&DtorsAndObjects) {
{
- ApplyDebugLocation NL(*this);
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(), FunctionArgList());
// Emit an artificial location for this function.
- ArtificialLocation AL(*this);
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
// Emit the dtors, in reverse order from construction.
for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index cb8eb8f..7b8368e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -16,23 +16,19 @@
#include "CGCleanup.h"
#include "CGObjCRuntime.h"
#include "TargetInfo.h"
+#include "clang/AST/Mangle.h"
#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"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
-static llvm::Constant *getAllocateExceptionFn(CodeGenModule &CGM) {
- // void *__cxa_allocate_exception(size_t thrown_size);
-
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false);
-
- return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
-}
-
static llvm::Constant *getFreeExceptionFn(CodeGenModule &CGM) {
// void __cxa_free_exception(void *thrown_exception);
@@ -42,44 +38,6 @@ static llvm::Constant *getFreeExceptionFn(CodeGenModule &CGM) {
return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
}
-static llvm::Constant *getThrowFn(CodeGenModule &CGM) {
- // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
- // void (*dest) (void *));
-
- llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy };
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false);
-
- return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
-}
-
-static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {
- // void *__cxa_get_exception_ptr(void*);
-
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
-
- return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
-}
-
-static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {
- // void *__cxa_begin_catch(void*);
-
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
-
- return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
-}
-
-static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {
- // void __cxa_end_catch();
-
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);
-
- return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
-}
-
static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) {
// void __cxa_call_unexpected(void *thrown_exception);
@@ -89,23 +47,30 @@ static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) {
return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
}
-static llvm::Constant *getTerminateFn(CodeGenModule &CGM) {
+llvm::Constant *CodeGenModule::getTerminateFn() {
// void __terminate();
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);
+ llvm::FunctionType::get(VoidTy, /*IsVarArgs=*/false);
StringRef name;
// In C++, use std::terminate().
- if (CGM.getLangOpts().CPlusPlus)
- name = "_ZSt9terminatev"; // FIXME: mangling!
- else if (CGM.getLangOpts().ObjC1 &&
- CGM.getLangOpts().ObjCRuntime.hasTerminate())
+ if (getLangOpts().CPlusPlus &&
+ getTarget().getCXXABI().isItaniumFamily()) {
+ name = "_ZSt9terminatev";
+ } else if (getLangOpts().CPlusPlus &&
+ getTarget().getCXXABI().isMicrosoft()) {
+ if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
+ name = "__std_terminate";
+ else
+ name = "\01?terminate@@YAXXZ";
+ } else if (getLangOpts().ObjC1 &&
+ getLangOpts().ObjCRuntime.hasTerminate())
name = "objc_terminate";
else
name = "abort";
- return CGM.CreateRuntimeFunction(FTy, name);
+ return CreateRuntimeFunction(FTy, name);
}
static llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM,
@@ -126,7 +91,12 @@ namespace {
// This function must have prototype void(void*).
const char *CatchallRethrowFn;
- static const EHPersonality &get(CodeGenModule &CGM);
+ static const EHPersonality &get(CodeGenModule &CGM,
+ const FunctionDecl *FD);
+ static const EHPersonality &get(CodeGenFunction &CGF) {
+ return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
+ }
+
static const EHPersonality GNU_C;
static const EHPersonality GNU_C_SJLJ;
static const EHPersonality GNU_C_SEH;
@@ -137,6 +107,9 @@ namespace {
static const EHPersonality GNU_CPlusPlus;
static const EHPersonality GNU_CPlusPlus_SJLJ;
static const EHPersonality GNU_CPlusPlus_SEH;
+ static const EHPersonality MSVC_except_handler;
+ static const EHPersonality MSVC_C_specific_handler;
+ static const EHPersonality MSVC_CxxFrameHandler3;
};
}
@@ -159,6 +132,12 @@ const EHPersonality
EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr };
const EHPersonality
EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr };
+const EHPersonality
+EHPersonality::MSVC_except_handler = { "_except_handler3", nullptr };
+const EHPersonality
+EHPersonality::MSVC_C_specific_handler = { "__C_specific_handler", nullptr };
+const EHPersonality
+EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr };
/// On Win64, use libgcc's SEH personality function. We fall back to dwarf on
/// other platforms, unless the user asked for SjLj exceptions.
@@ -231,9 +210,29 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
llvm_unreachable("bad runtime kind");
}
-const EHPersonality &EHPersonality::get(CodeGenModule &CGM) {
+static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) {
+ if (T.getArch() == llvm::Triple::x86)
+ return EHPersonality::MSVC_except_handler;
+ return EHPersonality::MSVC_C_specific_handler;
+}
+
+const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
+ const FunctionDecl *FD) {
const llvm::Triple &T = CGM.getTarget().getTriple();
const LangOptions &L = CGM.getLangOpts();
+
+ // Try to pick a personality function that is compatible with MSVC if we're
+ // not compiling Obj-C. Obj-C users better have an Obj-C runtime that supports
+ // the GCC-style personality function.
+ if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
+ if (L.SjLjExceptions)
+ return EHPersonality::GNU_CPlusPlus_SJLJ;
+ else if (FD && FD->usesSEHTry())
+ return getSEHPersonalityMSVC(T);
+ else
+ return EHPersonality::MSVC_CxxFrameHandler3;
+ }
+
if (L.CPlusPlus && L.ObjC1)
return getObjCXXPersonality(T, L);
else if (L.CPlusPlus)
@@ -318,7 +317,7 @@ void CodeGenModule::SimplifyPersonality() {
if (!LangOpts.ObjCRuntime.isNeXTFamily())
return;
- const EHPersonality &ObjCXX = EHPersonality::get(*this);
+ const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr);
const EHPersonality &CXX =
getCXXPersonality(getTarget().getTriple(), LangOpts);
if (&ObjCXX == &CXX)
@@ -369,17 +368,16 @@ namespace {
// differs from EmitAnyExprToMem only in that, if a final copy-ctor
// call is required, an exception within that copy ctor causes
// std::terminate to be invoked.
-static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e,
- llvm::Value *addr) {
+void CodeGenFunction::EmitAnyExprToExn(const Expr *e, llvm::Value *addr) {
// Make sure the exception object is cleaned up if there's an
// exception during initialization.
- CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr);
- EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin();
+ pushFullExprCleanup<FreeException>(EHCleanup, addr);
+ EHScopeStack::stable_iterator cleanup = EHStack.stable_begin();
// __cxa_allocate_exception returns a void*; we need to cast this
// to the appropriate type for the object.
- llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo();
- llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty);
+ llvm::Type *ty = ConvertTypeForMem(e->getType())->getPointerTo();
+ llvm::Value *typedAddr = Builder.CreateBitCast(addr, ty);
// FIXME: this isn't quite right! If there's a final unelided call
// to a copy constructor, then according to [except.terminate]p1 we
@@ -388,11 +386,11 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e,
// evaluated but before the exception is caught. But the best way
// to handle that is to teach EmitAggExpr to do the final copy
// differently if it can't be elided.
- CGF.EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
- /*IsInit*/ true);
+ EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
+ /*IsInit*/ true);
// Deactivate the cleanup block.
- CGF.DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr));
+ DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr));
}
llvm::Value *CodeGenFunction::getExceptionSlot() {
@@ -417,67 +415,18 @@ llvm::Value *CodeGenFunction::getSelectorFromSlot() {
void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
bool KeepInsertionPoint) {
- if (!E->getSubExpr()) {
- CGM.getCXXABI().emitRethrow(*this, /*isNoReturn*/true);
-
- // throw is an expression, and the expression emitters expect us
- // to leave ourselves at a valid insertion point.
- if (KeepInsertionPoint)
- EmitBlock(createBasicBlock("throw.cont"));
-
- return;
- }
-
- if (CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) {
- ErrorUnsupported(E, "throw expression");
- return;
- }
-
- QualType ThrowType = E->getSubExpr()->getType();
-
- if (ThrowType->isObjCObjectPointerType()) {
- const Stmt *ThrowStmt = E->getSubExpr();
- const ObjCAtThrowStmt S(E->getExprLoc(),
- const_cast<Stmt *>(ThrowStmt));
- CGM.getObjCRuntime().EmitThrowStmt(*this, S, false);
- // This will clear insertion point which was not cleared in
- // call to EmitThrowStmt.
- if (KeepInsertionPoint)
- EmitBlock(createBasicBlock("throw.cont"));
- return;
- }
-
- // Now allocate the exception object.
- llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
- uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
-
- llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(CGM);
- llvm::CallInst *ExceptionPtr =
- EmitNounwindRuntimeCall(AllocExceptionFn,
- llvm::ConstantInt::get(SizeTy, TypeSize),
- "exception");
-
- EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr);
-
- // Now throw the exception.
- llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
- /*ForEH=*/true);
-
- // The address of the destructor. If the exception type has a
- // trivial destructor (or isn't a record), we just pass null.
- llvm::Constant *Dtor = nullptr;
- if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!Record->hasTrivialDestructor()) {
- CXXDestructorDecl *DtorD = Record->getDestructor();
- Dtor = CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete);
- Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy);
+ if (const Expr *SubExpr = E->getSubExpr()) {
+ QualType ThrowType = SubExpr->getType();
+ if (ThrowType->isObjCObjectPointerType()) {
+ const Stmt *ThrowStmt = E->getSubExpr();
+ const ObjCAtThrowStmt S(E->getExprLoc(), const_cast<Stmt *>(ThrowStmt));
+ CGM.getObjCRuntime().EmitThrowStmt(*this, S, false);
+ } else {
+ CGM.getCXXABI().emitThrow(*this, E);
}
+ } else {
+ CGM.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
}
- if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy);
-
- llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
- EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
// throw is an expression, and the expression emitters expect us
// to leave ourselves at a valid insertion point.
@@ -509,6 +458,10 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
EHStack.pushTerminate();
}
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+ // TODO: Revisit exception specifications for the MS ABI. There is a way to
+ // encode these in an object file but MSVC doesn't do anything with it.
+ if (getTarget().getCXXABI().isMicrosoft())
+ return;
unsigned NumExceptions = Proto->getNumExceptions();
EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
@@ -543,8 +496,9 @@ static void emitFilterDispatchBlock(CodeGenFunction &CGF,
llvm::Value *zero = CGF.Builder.getInt32(0);
llvm::Value *failsFilter =
- CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails");
- CGF.Builder.CreateCondBr(failsFilter, unexpectedBB, CGF.getEHResumeBlock(false));
+ CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails");
+ CGF.Builder.CreateCondBr(failsFilter, unexpectedBB,
+ CGF.getEHResumeBlock(false));
CGF.EmitBlock(unexpectedBB);
}
@@ -582,6 +536,10 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
EHStack.popTerminate();
}
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+ // TODO: Revisit exception specifications for the MS ABI. There is a way to
+ // encode these in an object file but MSVC doesn't do anything with it.
+ if (getTarget().getCXXABI().isMicrosoft())
+ return;
EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin());
emitFilterDispatchBlock(*this, filterScope);
EHStack.popFilter();
@@ -589,11 +547,6 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
}
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
- if (CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) {
- ErrorUnsupported(&S, "try statement");
- return;
- }
-
EnterCXXTryStmt(S);
EmitStmt(S.getTryBlock());
ExitCXXTryStmt(S);
@@ -622,7 +575,8 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
if (CaughtType->isObjCObjectPointerType())
TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
else
- TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true);
+ TypeInfo =
+ CGM.getAddrOfCXXCatchHandlerType(CaughtType, C->getCaughtType());
CatchScope->setHandler(I, TypeInfo, Handler);
} else {
// No exception decl indicates '...', a catch-all.
@@ -695,8 +649,15 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
assert(EHStack.requiresLandingPad());
assert(!EHStack.empty());
- if (!CGM.getLangOpts().Exceptions)
- return nullptr;
+ // If exceptions are disabled, there are usually no landingpads. However, when
+ // SEH is enabled, functions using SEH still get landingpads.
+ const LangOptions &LO = CGM.getLangOpts();
+ if (!LO.Exceptions) {
+ if (!LO.Borland && !LO.MicrosoftExt)
+ return nullptr;
+ if (!currentFunctionUsesSEHTry())
+ return nullptr;
+ }
// Check the innermost scope for a cached landing pad. If this is
// a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
@@ -734,17 +695,19 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Save the current IR generation state.
CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
- ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
+ auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation);
- const EHPersonality &personality = EHPersonality::get(CGM);
+ const EHPersonality &personality = EHPersonality::get(*this);
+
+ if (!CurFn->hasPersonalityFn())
+ CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, personality));
// Create and configure the landing pad.
llvm::BasicBlock *lpad = createBasicBlock("lpad");
EmitBlock(lpad);
- llvm::LandingPadInst *LPadInst =
- Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr),
- getOpaquePersonalityFn(CGM, personality), 0);
+ llvm::LandingPadInst *LPadInst = Builder.CreateLandingPad(
+ llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr), 0);
llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);
Builder.CreateStore(LPadExn, getExceptionSlot());
@@ -762,8 +725,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
bool hasFilter = false;
SmallVector<llvm::Value*, 4> filterTypes;
llvm::SmallPtrSet<llvm::Value*, 4> catchTypes;
- for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end();
- I != E; ++I) {
+ for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); I != E;
+ ++I) {
switch (I->getKind()) {
case EHScope::Cleanup:
@@ -857,263 +820,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
return lpad;
}
-namespace {
- /// A cleanup to call __cxa_end_catch. In many cases, the caught
- /// exception type lets us state definitively that the thrown exception
- /// type does not have a destructor. In particular:
- /// - Catch-alls tell us nothing, so we have to conservatively
- /// assume that the thrown exception might have a destructor.
- /// - Catches by reference behave according to their base types.
- /// - Catches of non-record types will only trigger for exceptions
- /// of non-record types, which never have destructors.
- /// - Catches of record types can trigger for arbitrary subclasses
- /// of the caught type, so we have to assume the actual thrown
- /// exception type might have a throwing destructor, even if the
- /// caught type's destructor is trivial or nothrow.
- struct CallEndCatch : EHScopeStack::Cleanup {
- CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
- bool MightThrow;
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- if (!MightThrow) {
- CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
- return;
- }
-
- CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
- }
- };
-}
-
-/// Emits a call to __cxa_begin_catch and enters a cleanup to call
-/// __cxa_end_catch.
-///
-/// \param EndMightThrow - true if __cxa_end_catch might throw
-static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
- llvm::Value *Exn,
- bool EndMightThrow) {
- llvm::CallInst *call =
- CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
-
- CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
-
- return call;
-}
-
-/// A "special initializer" callback for initializing a catch
-/// parameter during catch initialization.
-static void InitCatchParam(CodeGenFunction &CGF,
- const VarDecl &CatchParam,
- llvm::Value *ParamAddr,
- SourceLocation Loc) {
- // Load the exception from where the landing pad saved it.
- llvm::Value *Exn = CGF.getExceptionFromSlot();
-
- CanQualType CatchType =
- CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
- llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
-
- // If we're catching by reference, we can just cast the object
- // pointer to the appropriate pointer.
- if (isa<ReferenceType>(CatchType)) {
- QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
- bool EndCatchMightThrow = CaughtType->isRecordType();
-
- // __cxa_begin_catch returns the adjusted object pointer.
- llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
-
- // We have no way to tell the personality function that we're
- // catching by reference, so if we're catching a pointer,
- // __cxa_begin_catch will actually return that pointer by value.
- if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
- QualType PointeeType = PT->getPointeeType();
-
- // When catching by reference, generally we should just ignore
- // this by-value pointer and use the exception object instead.
- if (!PointeeType->isRecordType()) {
-
- // Exn points to the struct _Unwind_Exception header, which
- // we have to skip past in order to reach the exception data.
- unsigned HeaderSize =
- CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
- AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);
-
- // However, if we're catching a pointer-to-record type that won't
- // work, because the personality function might have adjusted
- // the pointer. There's actually no way for us to fully satisfy
- // the language/ABI contract here: we can't use Exn because it
- // might have the wrong adjustment, but we can't use the by-value
- // pointer because it's off by a level of abstraction.
- //
- // The current solution is to dump the adjusted pointer into an
- // alloca, which breaks language semantics (because changing the
- // pointer doesn't change the exception) but at least works.
- // The better solution would be to filter out non-exact matches
- // and rethrow them, but this is tricky because the rethrow
- // really needs to be catchable by other sites at this landing
- // pad. The best solution is to fix the personality function.
- } else {
- // Pull the pointer for the reference type off.
- llvm::Type *PtrTy =
- cast<llvm::PointerType>(LLVMCatchTy)->getElementType();
-
- // Create the temporary and write the adjusted pointer into it.
- llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
- llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
- CGF.Builder.CreateStore(Casted, ExnPtrTmp);
-
- // Bind the reference to the temporary.
- AdjustedExn = ExnPtrTmp;
- }
- }
-
- llvm::Value *ExnCast =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
- CGF.Builder.CreateStore(ExnCast, ParamAddr);
- return;
- }
-
- // Scalars and complexes.
- TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);
- if (TEK != TEK_Aggregate) {
- llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
-
- // If the catch type is a pointer type, __cxa_begin_catch returns
- // the pointer by value.
- if (CatchType->hasPointerRepresentation()) {
- llvm::Value *CastExn =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
-
- switch (CatchType.getQualifiers().getObjCLifetime()) {
- case Qualifiers::OCL_Strong:
- CastExn = CGF.EmitARCRetainNonBlock(CastExn);
- // fallthrough
-
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- CGF.Builder.CreateStore(CastExn, ParamAddr);
- return;
-
- case Qualifiers::OCL_Weak:
- CGF.EmitARCInitWeak(ParamAddr, CastExn);
- return;
- }
- llvm_unreachable("bad ownership qualifier!");
- }
-
- // Otherwise, it returns a pointer into the exception object.
-
- llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
- llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
-
- LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);
- LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,
- CGF.getContext().getDeclAlign(&CatchParam));
- switch (TEK) {
- case TEK_Complex:
- CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
- /*init*/ true);
- return;
- case TEK_Scalar: {
- llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);
- CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
- return;
- }
- case TEK_Aggregate:
- llvm_unreachable("evaluation kind filtered out!");
- }
- llvm_unreachable("bad evaluation kind");
- }
-
- assert(isa<RecordType>(CatchType) && "unexpected catch type!");
-
- llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
-
- // Check for a copy expression. If we don't have a copy expression,
- // that means a trivial copy is okay.
- const Expr *copyExpr = CatchParam.getInit();
- if (!copyExpr) {
- llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
- llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
- CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);
- return;
- }
-
- // We have to call __cxa_get_exception_ptr to get the adjusted
- // pointer before copying.
- llvm::CallInst *rawAdjustedExn =
- CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
-
- // Cast that to the appropriate type.
- llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
-
- // The copy expression is defined in terms of an OpaqueValueExpr.
- // Find it and map it to the adjusted expression.
- CodeGenFunction::OpaqueValueMapping
- opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
- CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
-
- // Call the copy ctor in a terminate scope.
- CGF.EHStack.pushTerminate();
-
- // Perform the copy construction.
- CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);
- CGF.EmitAggExpr(copyExpr,
- AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),
- AggValueSlot::IsNotDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
-
- // Leave the terminate scope.
- CGF.EHStack.popTerminate();
-
- // Undo the opaque value mapping.
- opaque.pop();
-
- // Finally we can call __cxa_begin_catch.
- CallBeginCatch(CGF, Exn, true);
-}
-
-/// Begins a catch statement by initializing the catch variable and
-/// calling __cxa_begin_catch.
-static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
- // We have to be very careful with the ordering of cleanups here:
- // C++ [except.throw]p4:
- // The destruction [of the exception temporary] occurs
- // immediately after the destruction of the object declared in
- // the exception-declaration in the handler.
- //
- // So the precise ordering is:
- // 1. Construct catch variable.
- // 2. __cxa_begin_catch
- // 3. Enter __cxa_end_catch cleanup
- // 4. Enter dtor cleanup
- //
- // We do this by using a slightly abnormal initialization process.
- // Delegation sequence:
- // - ExitCXXTryStmt opens a RunCleanupsScope
- // - EmitAutoVarAlloca creates the variable and debug info
- // - InitCatchParam initializes the variable from the exception
- // - CallBeginCatch calls __cxa_begin_catch
- // - CallBeginCatch enters the __cxa_end_catch cleanup
- // - EmitAutoVarCleanups enters the variable destructor cleanup
- // - EmitCXXTryStmt emits the code for the catch body
- // - EmitCXXTryStmt close the RunCleanupsScope
-
- VarDecl *CatchParam = S->getExceptionDecl();
- if (!CatchParam) {
- llvm::Value *Exn = CGF.getExceptionFromSlot();
- CallBeginCatch(CGF, Exn, true);
- return;
- }
-
- // Emit the local.
- CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
- InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());
- CGF.EmitAutoVarCleanups(var);
-}
-
/// Emit the structure of the dispatch block for the given catch scope.
/// It is an invariant that the dispatch block already exists.
static void emitCatchDispatchBlock(CodeGenFunction &CGF,
@@ -1252,11 +958,10 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
RunCleanupsScope CatchScope(*this);
// Initialize the catch variable and set up the cleanups.
- BeginCatch(*this, C);
+ CGM.getCXXABI().emitBeginCatch(*this, C);
// Emit the PGO counter increment.
- RegionCounter CatchCnt = getPGORegionCounter(C);
- CatchCnt.beginRegion(Builder);
+ incrementProfileCounter(C);
// Perform the body of the catch.
EmitStmt(C->getHandlerBlock());
@@ -1284,9 +989,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
Builder.CreateBr(ContBB);
}
- RegionCounter ContCnt = getPGORegionCounter(&S);
EmitBlock(ContBB);
- ContCnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
}
namespace {
@@ -1480,68 +1184,6 @@ void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) {
CGF.PopCleanupBlock();
}
-/// In a terminate landing pad, should we use __clang__call_terminate
-/// or just a naked call to std::terminate?
-///
-/// __clang_call_terminate calls __cxa_begin_catch, which then allows
-/// std::terminate to usefully report something about the
-/// violating exception.
-static bool useClangCallTerminate(CodeGenModule &CGM) {
- // Only do this for Itanium-family ABIs in C++ mode.
- return (CGM.getLangOpts().CPlusPlus &&
- CGM.getTarget().getCXXABI().isItaniumFamily());
-}
-
-/// Get or define the following function:
-/// void @__clang_call_terminate(i8* %exn) nounwind noreturn
-/// This code is used only in C++.
-static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
- llvm::FunctionType *fnTy =
- llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
- llvm::Constant *fnRef =
- CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");
-
- llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);
- if (fn && fn->empty()) {
- fn->setDoesNotThrow();
- fn->setDoesNotReturn();
-
- // What we really want is to massively penalize inlining without
- // forbidding it completely. The difference between that and
- // 'noinline' is negligible.
- fn->addFnAttr(llvm::Attribute::NoInline);
-
- // Allow this function to be shared across translation units, but
- // we don't want it to turn into an exported symbol.
- fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
- fn->setVisibility(llvm::Function::HiddenVisibility);
-
- // Set up the function.
- llvm::BasicBlock *entry =
- llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
- CGBuilderTy builder(entry);
-
- // Pull the exception pointer out of the parameter list.
- llvm::Value *exn = &*fn->arg_begin();
-
- // Call __cxa_begin_catch(exn).
- llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
- catchCall->setDoesNotThrow();
- catchCall->setCallingConv(CGM.getRuntimeCC());
-
- // Call std::terminate().
- llvm::CallInst *termCall = builder.CreateCall(getTerminateFn(CGM));
- termCall->setDoesNotThrow();
- termCall->setDoesNotReturn();
- termCall->setCallingConv(CGM.getRuntimeCC());
-
- // std::terminate cannot return.
- builder.CreateUnreachable();
- }
-
- return fnRef;
-}
-
llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
if (TerminateLandingPad)
return TerminateLandingPad;
@@ -1553,20 +1195,20 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
Builder.SetInsertPoint(TerminateLandingPad);
// Tell the backend that this is a landing pad.
- const EHPersonality &Personality = EHPersonality::get(CGM);
- llvm::LandingPadInst *LPadInst =
- Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr),
- getOpaquePersonalityFn(CGM, Personality), 0);
+ const EHPersonality &Personality = EHPersonality::get(*this);
+
+ if (!CurFn->hasPersonalityFn())
+ CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality));
+
+ llvm::LandingPadInst *LPadInst = Builder.CreateLandingPad(
+ llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr), 0);
LPadInst->addClause(getCatchAllValue(*this));
- llvm::CallInst *terminateCall;
- if (useClangCallTerminate(CGM)) {
- // Extract out the exception pointer.
- llvm::Value *exn = Builder.CreateExtractValue(LPadInst, 0);
- terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn);
- } else {
- terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));
- }
+ llvm::Value *Exn = 0;
+ if (getLangOpts().CPlusPlus)
+ Exn = Builder.CreateExtractValue(LPadInst, 0);
+ llvm::CallInst *terminateCall =
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
terminateCall->setDoesNotReturn();
Builder.CreateUnreachable();
@@ -1586,14 +1228,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
// end of the function by FinishFunction.
TerminateHandler = createBasicBlock("terminate.handler");
Builder.SetInsertPoint(TerminateHandler);
- llvm::CallInst *terminateCall;
- if (useClangCallTerminate(CGM)) {
- // Load the exception pointer.
- llvm::Value *exn = getExceptionFromSlot();
- terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn);
- } else {
- terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));
- }
+ llvm::Value *Exn = 0;
+ if (getLangOpts().CPlusPlus)
+ Exn = getExceptionFromSlot();
+ llvm::CallInst *terminateCall =
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
terminateCall->setDoesNotReturn();
Builder.CreateUnreachable();
@@ -1612,15 +1251,14 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
EHResumeBlock = createBasicBlock("eh.resume");
Builder.SetInsertPoint(EHResumeBlock);
- const EHPersonality &Personality = EHPersonality::get(CGM);
+ const EHPersonality &Personality = EHPersonality::get(*this);
// This can always be a call because we necessarily didn't find
// anything on the EH stack which needs our help.
const char *RethrowName = Personality.CatchallRethrowFn;
if (RethrowName != nullptr && !isCleanup) {
EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName),
- getExceptionFromSlot())
- ->setDoesNotReturn();
+ getExceptionFromSlot())->setDoesNotReturn();
Builder.CreateUnreachable();
Builder.restoreIP(SavedIP);
return EHResumeBlock;
@@ -1642,9 +1280,510 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
}
void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
- CGM.ErrorUnsupported(&S, "SEH __try");
+ EnterSEHTryStmt(S);
+ {
+ JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
+
+ SEHTryEpilogueStack.push_back(&TryExit);
+ EmitStmt(S.getTryBlock());
+ SEHTryEpilogueStack.pop_back();
+
+ if (!TryExit.getBlock()->use_empty())
+ EmitBlock(TryExit.getBlock(), /*IsFinished=*/true);
+ else
+ delete TryExit.getBlock();
+ }
+ ExitSEHTryStmt(S);
+}
+
+namespace {
+struct PerformSEHFinally : EHScopeStack::Cleanup {
+ llvm::Function *OutlinedFinally;
+ PerformSEHFinally(llvm::Function *OutlinedFinally)
+ : OutlinedFinally(OutlinedFinally) {}
+
+ void Emit(CodeGenFunction &CGF, Flags F) override {
+ ASTContext &Context = CGF.getContext();
+ 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]);
+ 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, FPT,
+ /*chainCall=*/false);
+
+ CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
+ }
+};
+}
+
+namespace {
+/// Find all local variable captures in the statement.
+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);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
+ }
+
+ void VisitDeclRefExpr(const DeclRefExpr *E) {
+ // If this is already a capture, just make sure we capture 'this'.
+ if (E->refersToEnclosingVariableOrCapture()) {
+ Captures.push_back(ParentThis);
+ return;
+ }
+
+ const auto *D = dyn_cast<VarDecl>(E->getDecl());
+ if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
+ Captures.push_back(D);
+ }
+
+ 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,
+ bool IsFilter) {
+ // Find all captures in the Stmt.
+ CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
+ Finder.Visit(OutlinedStmt);
+
+ // 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;
+ }
+
+ 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.localrecover calls for all captures.
+ for (const VarDecl *VD : Finder.Captures) {
+ if (isa<ImplicitParamDecl>(VD)) {
+ CGM.ErrorUnsupported(VD, "'this' captured by SEH");
+ CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType()));
+ continue;
+ }
+ if (VD->getType()->isVariablyModifiedType()) {
+ CGM.ErrorUnsupported(VD, "VLA captured by SEH");
+ continue;
+ }
+ assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
+ "captured non-local variable");
+
+ // If this decl hasn't been declared yet, it will be declared in the
+ // OutlinedStmt.
+ auto I = ParentCGF.LocalDeclMap.find(VD);
+ if (I == ParentCGF.LocalDeclMap.end())
+ continue;
+ llvm::Value *ParentVar = I->second;
+
+ LocalDeclMap[VD] =
+ recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
+ }
+
+ 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,
+ 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);
+
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::Function *Fn = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
+ // The filter is either in the same comdat as the function, or it's internal.
+ if (llvm::Comdat *C = ParentFn->getComdat()) {
+ Fn->setComdat(C);
+ } else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
+ llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
+ ParentFn->setComdat(C);
+ Fn->setComdat(C);
+ } else {
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+ }
+
+ IsOutlinedSEHHelper = true;
+
+ StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
+ OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
+
+ CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
+ EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);
+}
+
+/// Create a stub filter function that will ultimately hold the code of the
+/// filter expression. The EH preparation passes in LLVM will outline the code
+/// from the main function body into this stub.
+llvm::Function *
+CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
+ const SEHExceptStmt &Except) {
+ const Expr *FilterExpr = Except.getFilterExpr();
+ startOutlinedSEHHelper(ParentCGF, true, FilterExpr);
+
+ // Emit the original filter expression, convert to i32, and return.
+ llvm::Value *R = EmitScalarExpr(FilterExpr);
+ R = Builder.CreateIntCast(R, ConvertType(getContext().LongTy),
+ FilterExpr->getType()->isSignedIntegerType());
+ Builder.CreateStore(R, ReturnValue);
+
+ FinishFunction(FilterExpr->getLocEnd());
+
+ return CurFn;
+}
+
+llvm::Function *
+CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally) {
+ const Stmt *FinallyBlock = Finally.getBlock();
+ startOutlinedSEHHelper(ParentCGF, false, 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);
+
+ FinishFunction(FinallyBlock->getLocEnd());
+
+ return CurFn;
+}
+
+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;
+ // };
+ // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode;
+ llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo();
+ llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
+ 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);
+ 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 (!SEHInfo)
+ return llvm::UndefValue::get(Int8PtrTy);
+ assert(SEHInfo->getType() == Int8PtrTy);
+ return SEHInfo;
+}
+
+llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
+ assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
+ return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back());
+}
+
+llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
+ // Abnormal termination is just the first parameter to the outlined finally
+ // helper.
+ auto AI = CurFn->arg_begin();
+ return Builder.CreateZExt(&*AI, Int32Ty);
+}
+
+void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
+ // Outline the finally block.
+ llvm::Function *FinallyFunc =
+ HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
+
+ // Push a cleanup for __finally blocks.
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
+ return;
+ }
+
+ // Otherwise, we must have an __except block.
+ 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". 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 (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C &&
+ C->isOneValue()) {
+ CatchScope->setCatchAllHandler(0, createBasicBlock("__except"));
+ return;
+ }
+
+ // In general, we have to emit an outlined filter function. Use the function
+ // in place of the RTTI typeinfo global that C++ EH uses.
+ llvm::Function *FilterFunc =
+ HelperCGF.GenerateSEHFilterFunction(*this, *Except);
+ llvm::Constant *OpaqueFunc =
+ llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
+ CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except"));
+}
+
+void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
+ // Just pop the cleanup if it's a __finally block.
+ if (S.getFinallyHandler()) {
+ PopCleanupBlock();
+ return;
+ }
+
+ // Otherwise, we must have an __except block.
+ const SEHExceptStmt *Except = S.getExceptHandler();
+ assert(Except && "__try must have __finally xor __except");
+ EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
+
+ // Don't emit the __except block if the __try block lacked invokes.
+ // TODO: Model unwind edges from instructions, either with iload / istore or
+ // a try body function.
+ if (!CatchScope.hasEHBranches()) {
+ CatchScope.clearHandlerBlocks();
+ EHStack.popCatch();
+ SEHCodeSlotStack.pop_back();
+ return;
+ }
+
+ // The fall-through block.
+ llvm::BasicBlock *ContBB = createBasicBlock("__try.cont");
+
+ // We just emitted the body of the __try; jump to the continue block.
+ if (HaveInsertPoint())
+ Builder.CreateBr(ContBB);
+
+ // Check if our filter function returned true.
+ emitCatchDispatchBlock(*this, CatchScope);
+
+ // Grab the block before we pop the handler.
+ llvm::BasicBlock *ExceptBB = CatchScope.getHandler(0).Block;
+ EHStack.popCatch();
+
+ 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);
+
+ EmitBlock(ContBB);
}
void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) {
- CGM.ErrorUnsupported(&S, "SEH __leave");
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
+
+ // This must be a __leave from a __finally block, which we warn on and is UB.
+ // Just emit unreachable.
+ if (!isSEHTryScope()) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ return;
+ }
+
+ EmitBranchThroughCleanup(*SEHTryEpilogueStack.back());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index ce7679c..9c3dfe5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -31,6 +31,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
using namespace CodeGen;
@@ -300,9 +301,26 @@ createReferenceTemporary(CodeGenFunction &CGF,
const MaterializeTemporaryExpr *M, const Expr *Inner) {
switch (M->getStorageDuration()) {
case SD_FullExpression:
- case SD_Automatic:
- return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
-
+ case SD_Automatic: {
+ // If we have a constant temporary array or record try to promote it into a
+ // constant global under the same rules a normal constant would've been
+ // promoted. This is easier on the optimizer and generally emits fewer
+ // instructions.
+ QualType Ty = Inner->getType();
+ if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
+ (Ty->isArrayType() || Ty->isRecordType()) &&
+ CGF.CGM.isTypeConstant(Ty, true))
+ if (llvm::Constant *Init = CGF.CGM.EmitConstantExpr(Inner, Ty, &CGF)) {
+ auto *GV = new llvm::GlobalVariable(
+ CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp");
+ GV->setAlignment(
+ CGF.getContext().getTypeAlignInChars(Ty).getQuantity());
+ // FIXME: Should we put the new global into a COMDAT?
+ return GV;
+ }
+ return CGF.CreateMemTemp(Ty, "ref.tmp");
+ }
case SD_Thread:
case SD_Static:
return CGF.CGM.GetAddrOfGlobalTemporary(M, Inner);
@@ -324,14 +342,15 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
llvm::Value *Object = createReferenceTemporary(*this, M, E);
- LValue RefTempDst = MakeAddrLValue(Object, M->getType());
-
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+ Object = llvm::ConstantExpr::getBitCast(
+ Var, ConvertTypeForMem(E->getType())->getPointerTo());
// We should not have emitted the initializer for this temporary as a
// constant.
assert(!Var->hasInitializer());
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
+ LValue RefTempDst = MakeAddrLValue(Object, M->getType());
switch (getEvaluationKind(E->getType())) {
default: llvm_unreachable("expected scalar or aggregate expression");
@@ -370,8 +389,11 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
// Create and initialize the reference temporary.
llvm::Value *Object = createReferenceTemporary(*this, M, E);
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
- // If the temporary is a global and has a constant initializer, we may
- // have already initialized it.
+ Object = llvm::ConstantExpr::getBitCast(
+ Var, ConvertTypeForMem(E->getType())->getPointerTo());
+ // If the temporary is a global and has a constant initializer or is a
+ // constant temporary that we promoted to a global, we may have already
+ // initialized it.
if (!Var->hasInitializer()) {
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
@@ -478,7 +500,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
SanitizerScope SanScope(this);
- SmallVector<std::pair<llvm::Value *, SanitizerKind>, 3> Checks;
+ SmallVector<std::pair<llvm::Value *, SanitizerMask>, 3> Checks;
llvm::BasicBlock *Done = nullptr;
bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
@@ -513,7 +535,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Min = Builder.getFalse();
llvm::Value *CastAddr = Builder.CreateBitCast(Address, Int8PtrTy);
llvm::Value *LargeEnough =
- Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
+ Builder.CreateICmpUGE(Builder.CreateCall(F, {CastAddr, Min}),
llvm::ConstantInt::get(IntPtrTy, Size));
Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
}
@@ -807,6 +829,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
/// length type, this is not possible.
///
LValue CodeGenFunction::EmitLValue(const Expr *E) {
+ ApplyDebugLocation DL(*this, E);
switch (E->getStmtClass()) {
default: return EmitUnsupportedLValue(E, "l-value expression");
@@ -819,10 +842,14 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
case Expr::BinaryOperatorClass:
return EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
- case Expr::CompoundAssignOperatorClass:
- if (!E->getType()->isAnyComplexType())
+ case Expr::CompoundAssignOperatorClass: {
+ QualType Ty = E->getType();
+ if (const AtomicType *AT = Ty->getAs<AtomicType>())
+ Ty = AT->getValueType();
+ if (!Ty->isAnyComplexType())
return EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
return EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+ }
case Expr::CallExprClass:
case Expr::CXXMemberCallExprClass:
case Expr::CXXOperatorCallExprClass:
@@ -1135,7 +1162,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
}
// Atomic operations have to be done on integral types.
- if (Ty->isAtomicType()) {
+ if (Ty->isAtomicType() || typeIsSuitableForInlineAtomic(Ty, Volatile)) {
LValue lvalue = LValue::MakeAddr(Addr, Ty,
CharUnits::fromQuantity(Alignment),
getContext(), TBAAInfo);
@@ -1178,7 +1205,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty)
};
- SanitizerKind Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
+ SanitizerMask Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
EmitCheck(std::make_pair(Check, Kind), "load_invalid_value", StaticArgs,
EmitCheckValue(Load));
}
@@ -1254,7 +1281,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
Value = EmitToMemory(Value, Ty);
- if (Ty->isAtomicType()) {
+ if (Ty->isAtomicType() ||
+ (!isInit && typeIsSuitableForInlineAtomic(Ty, Volatile))) {
EmitAtomicStore(RValue::get(Value),
LValue::MakeAddr(Addr, Ty,
CharUnits::fromQuantity(Alignment),
@@ -1328,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);
@@ -1531,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();
@@ -1547,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()))
@@ -1575,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) {
@@ -1692,8 +1721,8 @@ void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
llvm::Value *Value = Src.getScalarVal();
if (OrigTy->isPointerTy())
Value = Builder.CreatePtrToInt(Value, Ty);
- Builder.CreateCall2(F, llvm::MetadataAsValue::get(Ty->getContext(), RegName),
- Value);
+ Builder.CreateCall(
+ F, {llvm::MetadataAsValue::get(Ty->getContext(), RegName), Value});
}
// setObjCGCLValueClass - sets class of the lvalue for the purpose of
@@ -1807,7 +1836,7 @@ EmitBitCastOfLValueToProperType(CodeGenFunction &CGF,
static LValue EmitThreadPrivateVarDeclLValue(
CodeGenFunction &CGF, const VarDecl *VD, QualType T, llvm::Value *V,
llvm::Type *RealVarTy, CharUnits Alignment, SourceLocation Loc) {
- V = CGF.CGM.getOpenMPRuntime().getOMPAddrOfThreadPrivate(CGF, VD, V, Loc);
+ V = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, V, Loc);
V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
return CGF.MakeAddrLValue(V, T, Alignment);
}
@@ -2050,9 +2079,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
assert(E->getSubExpr()->getType()->isAnyComplexType());
unsigned Idx = E->getOpcode() == UO_Imag;
- return MakeAddrLValue(Builder.CreateStructGEP(LV.getAddress(),
- Idx, "idx"),
- ExprTy);
+ return MakeAddrLValue(
+ Builder.CreateStructGEP(nullptr, LV.getAddress(), Idx, "idx"), ExprTy);
}
case UO_PreInc:
case UO_PreDec: {
@@ -2217,7 +2245,8 @@ enum class CheckRecoverableKind {
};
}
-static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) {
+static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) {
+ assert(llvm::countPopulation(Kind) == 1);
switch (Kind) {
case SanitizerKind::Vptr:
return CheckRecoverableKind::AlwaysRecoverable;
@@ -2264,7 +2293,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
}
void CodeGenFunction::EmitCheck(
- ArrayRef<std::pair<llvm::Value *, SanitizerKind>> Checked,
+ ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs) {
assert(IsSanitizerScope);
@@ -2272,15 +2301,24 @@ void CodeGenFunction::EmitCheck(
llvm::Value *FatalCond = nullptr;
llvm::Value *RecoverableCond = nullptr;
+ llvm::Value *TrapCond = nullptr;
for (int i = 0, n = Checked.size(); i < n; ++i) {
llvm::Value *Check = Checked[i].first;
+ // -fsanitize-trap= overrides -fsanitize-recover=.
llvm::Value *&Cond =
- CGM.getCodeGenOpts().SanitizeRecover.has(Checked[i].second)
- ? RecoverableCond
- : FatalCond;
+ CGM.getCodeGenOpts().SanitizeTrap.has(Checked[i].second)
+ ? TrapCond
+ : CGM.getCodeGenOpts().SanitizeRecover.has(Checked[i].second)
+ ? RecoverableCond
+ : FatalCond;
Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check;
}
+ if (TrapCond)
+ EmitTrapCheck(TrapCond);
+ if (!FatalCond && !RecoverableCond)
+ return;
+
llvm::Value *JointCond;
if (FatalCond && RecoverableCond)
JointCond = Builder.CreateAnd(FatalCond, RecoverableCond);
@@ -2298,15 +2336,6 @@ void CodeGenFunction::EmitCheck(
}
#endif
- if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
- assert(RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
- "Runtime call required for AlwaysRecoverable kind!");
- // Assume that -fsanitize-undefined-trap-on-error overrides
- // -fsanitize-recover= options, as we can only print meaningful error
- // message and recover if we have a runtime support.
- return EmitTrapCheck(JointCond);
- }
-
llvm::BasicBlock *Cont = createBasicBlock("cont");
llvm::BasicBlock *Handlers = createBasicBlock("handler." + CheckName);
llvm::Instruction *Branch = Builder.CreateCondBr(JointCond, Cont, Handlers);
@@ -2375,8 +2404,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
TrapBB = createBasicBlock("trap");
Builder.CreateCondBr(Checked, Cont, TrapBB);
EmitBlock(TrapBB);
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap);
- llvm::CallInst *TrapCall = Builder.CreateCall(F);
+ llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
TrapCall->setDoesNotReturn();
TrapCall->setDoesNotThrow();
Builder.CreateUnreachable();
@@ -2387,6 +2415,17 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
EmitBlock(Cont);
}
+llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+ llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID));
+
+ if (!CGM.getCodeGenOpts().TrapFuncName.empty())
+ TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
+ "trap-func-name",
+ CGM.getCodeGenOpts().TrapFuncName);
+
+ return TrapCall;
+}
+
/// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an
/// array to pointer, return the array subexpression.
static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
@@ -2648,7 +2687,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
unsigned Idx = RL.getLLVMFieldNo(field);
if (Idx != 0)
// For structs, we GEP to the field that the record layout suggests.
- Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ Addr = Builder.CreateStructGEP(nullptr, Addr, Idx, field->getName());
// Get the access type.
llvm::Type *PtrTy = llvm::Type::getIntNPtrTy(
getLLVMContext(), Info.StorageSize,
@@ -2683,7 +2722,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
} else {
// For structs, we GEP to the field that the record layout suggests.
unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
- addr = Builder.CreateStructGEP(addr, idx, field->getName());
+ addr = Builder.CreateStructGEP(nullptr, addr, idx, field->getName());
// If this is a reference field, load the reference right now.
if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
@@ -2762,7 +2801,7 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(Base.getAddress(), idx);
+ llvm::Value *V = Builder.CreateStructGEP(nullptr, Base.getAddress(), idx);
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
// Make sure that the address is pointing to the right type. This is critical
@@ -2834,7 +2873,6 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
}
OpaqueValueMapping binding(*this, expr);
- RegionCounter Cnt = getPGORegionCounter(expr);
const Expr *condExpr = expr->getCond();
bool CondExprBool;
@@ -2845,7 +2883,7 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
if (!ContainsLabel(dead)) {
// If the true case is live, we need to track its region.
if (CondExprBool)
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(expr);
return EmitLValue(live);
}
}
@@ -2855,11 +2893,11 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
llvm::BasicBlock *contBlock = createBasicBlock("cond.end");
ConditionalEvaluation eval(*this);
- EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock, Cnt.getCount());
+ EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock, getProfileCount(expr));
// Any temporaries created here are conditional.
EmitBlock(lhsBlock);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(expr);
eval.begin(*this);
Optional<LValue> lhs =
EmitLValueOrThrowExpression(*this, expr->getTrueExpr());
@@ -3007,6 +3045,10 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(),
Derived, E->getType());
+ if (SanOpts.has(SanitizerKind::CFIDerivedCast))
+ EmitVTablePtrCheckForCast(E->getType(), Derived, /*MayBeNull=*/false,
+ CFITCK_DerivedCast, E->getLocStart());
+
return MakeAddrLValue(Derived, E->getType());
}
case CK_LValueBitCast: {
@@ -3016,6 +3058,11 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
ConvertType(CE->getTypeAsWritten()));
+
+ if (SanOpts.has(SanitizerKind::CFIUnrelatedCast))
+ EmitVTablePtrCheckForCast(E->getType(), V, /*MayBeNull=*/false,
+ CFITCK_UnrelatedCast, E->getLocStart());
+
return MakeAddrLValue(V, E->getType());
}
case CK_ObjCObjectLValueCast: {
@@ -3059,16 +3106,6 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV,
RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
- // Force column info to be generated so we can differentiate
- // multiple call sites on the same line in the debug info.
- // FIXME: This is insufficient. Two calls coming from the same macro
- // expansion will still get the same line/column and break debug info. It's
- // possible that LLVM can be fixed to not rely on this uniqueness, at which
- // point this workaround can be removed.
- ApplyDebugLocation DL(*this, E->getLocStart(),
- E->getDirectCallee() &&
- E->getDirectCallee()->isInlineSpecified());
-
// Builtins never have block type.
if (E->getCallee()->getType()->isBlockPointerType())
return EmitBlockCallExpr(E, ReturnValue);
@@ -3202,7 +3239,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
if (!RV.isScalar())
return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
- assert(E->getCallReturnType()->isReferenceType() &&
+ assert(E->getCallReturnType(getContext())->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
@@ -3328,16 +3365,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const auto *FnType =
cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
- // Force column info to differentiate multiple inlined call sites on
- // the same line, analoguous to EmitCallExpr.
- // FIXME: This is insufficient. Two calls coming from the same macro expansion
- // will still get the same line/column and break debug info. It's possible
- // that LLVM can be fixed to not rely on this uniqueness, at which point this
- // workaround can be removed.
- bool ForceColumnInfo = false;
- if (const FunctionDecl* FD = dyn_cast_or_null<const FunctionDecl>(TargetDecl))
- ForceColumnInfo = FD->isInlineSpecified();
-
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
if (llvm::Constant *PrefixSig =
@@ -3355,7 +3382,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
Callee, llvm::PointerType::getUnqual(PrefixStructTy));
llvm::Value *CalleeSigPtr =
- Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 0);
+ Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
llvm::Value *CalleeSig = Builder.CreateLoad(CalleeSigPtr);
llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig);
@@ -3365,7 +3392,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitBlock(TypeCheck);
llvm::Value *CalleeRTTIPtr =
- Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 1);
+ Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
llvm::Value *CalleeRTTI = Builder.CreateLoad(CalleeRTTIPtr);
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
@@ -3386,8 +3413,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)),
CGM.getContext().VoidPtrTy);
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arg_begin(),
- E->arg_end(), E->getDirectCallee(), /*ParamsToSkip*/ 0,
- ForceColumnInfo);
+ E->arg_end(), E->getDirectCallee(), /*ParamsToSkip*/ 0);
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
Args, FnType, /*isChainCall=*/Chain);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
index 4cf94c0..883b76b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
@@ -34,6 +34,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
CodeGenFunction &CGF;
CGBuilderTy &Builder;
AggValueSlot Dest;
+ bool IsResultUnused;
/// We want to use 'dest' as the return slot except under two
/// conditions:
@@ -48,7 +49,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
if (!shouldUseDestForReturnSlot())
return ReturnValueSlot();
- return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile());
+ return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile(), IsResultUnused);
}
AggValueSlot EnsureSlot(QualType T) {
@@ -61,9 +62,9 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
}
public:
- AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest)
- : CGF(cgf), Builder(CGF.Builder), Dest(Dest) {
- }
+ AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
+ : CGF(cgf), Builder(CGF.Builder), Dest(Dest),
+ IsResultUnused(IsResultUnused) { }
//===--------------------------------------------------------------------===//
// Utilities
@@ -98,6 +99,11 @@ public:
// Visitor Methods
//===--------------------------------------------------------------------===//
+ void Visit(Expr *E) {
+ ApplyDebugLocation DL(CGF, E);
+ StmtVisitor<AggExprEmitter>::Visit(E);
+ }
+
void VisitStmt(Stmt *S) {
CGF.ErrorUnsupported(S, "aggregate expression");
}
@@ -154,10 +160,12 @@ public:
EmitAggLoadOfLValue(E);
}
+ void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E);
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
void VisitChooseExpr(const ChooseExpr *CE);
void VisitInitListExpr(InitListExpr *E);
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+ void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
Visit(DAE->getExpr());
}
@@ -207,7 +215,7 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
LValue LV = CGF.EmitLValue(E);
// If the type of the l-value is atomic, then do an atomic load.
- if (LV.getType()->isAtomicType()) {
+ if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) {
CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest);
return;
}
@@ -579,7 +587,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
case CK_ToUnion: {
- if (Dest.isIgnored()) break;
+ // Evaluate even if the destination is ignored.
+ if (Dest.isIgnored()) {
+ CGF.EmitAnyExpr(E->getSubExpr(), AggValueSlot::ignored(),
+ /*ignoreResult=*/true);
+ break;
+ }
// GCC union extension
QualType Ty = E->getSubExpr()->getType();
@@ -640,7 +653,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// Build a GEP to refer to the subobject.
llvm::Value *valueAddr =
- CGF.Builder.CreateStructGEP(valueDest.getAddr(), 0);
+ CGF.Builder.CreateStructGEP(nullptr, valueDest.getAddr(), 0);
valueDest = AggValueSlot::forAddr(valueAddr,
valueDest.getAlignment(),
valueDest.getQualifiers(),
@@ -661,7 +674,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
llvm::Value *valueAddr =
- Builder.CreateStructGEP(atomicSlot.getAddr(), 0);
+ Builder.CreateStructGEP(nullptr, atomicSlot.getAddr(), 0);
RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
return EmitFinalDestCopy(valueType, rvalue);
}
@@ -736,7 +749,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
- if (E->getCallReturnType()->isReferenceType()) {
+ if (E->getCallReturnType(CGF.getContext())->isReferenceType()) {
EmitAggLoadOfLValue(E);
return;
}
@@ -860,7 +873,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
LValue LHS = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
// That copy is an atomic copy if the LHS is atomic.
- if (LHS.getType()->isAtomicType()) {
+ if (LHS.getType()->isAtomicType() ||
+ CGF.LValueIsSuitableForInlineAtomic(LHS)) {
CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false);
return;
}
@@ -877,7 +891,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// If we have an atomic type, evaluate into the destination and then
// do an atomic copy.
- if (LHS.getType()->isAtomicType()) {
+ if (LHS.getType()->isAtomicType() ||
+ CGF.LValueIsSuitableForInlineAtomic(LHS)) {
EnsureDest(E->getRHS()->getType());
Visit(E->getRHS());
CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false);
@@ -909,16 +924,16 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// Bind the common expression if necessary.
CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- RegionCounter Cnt = CGF.getPGORegionCounter(E);
CodeGenFunction::ConditionalEvaluation eval(CGF);
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, Cnt.getCount());
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock,
+ CGF.getProfileCount(E));
// Save whether the destination's lifetime is externally managed.
bool isExternallyDestructed = Dest.isExternallyDestructed();
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Visit(E->getTrueExpr());
eval.end(CGF);
@@ -1043,6 +1058,9 @@ AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
return;
} else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) {
return EmitNullInitializationToLValue(LV);
+ } else if (isa<NoInitExpr>(E)) {
+ // Do nothing.
+ return;
} else if (type->isReferenceType()) {
RValue RV = CGF.EmitReferenceBindingToExpr(E);
return CGF.EmitStoreThroughLValue(RV, LV);
@@ -1263,6 +1281,15 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
cleanupDominator->eraseFromParent();
}
+void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+ AggValueSlot Dest = EnsureSlot(E->getType());
+
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
+ Dest.getAlignment());
+ EmitInitializationToLValue(E->getBase(), DestLV);
+ VisitInitListExpr(E->getUpdater());
+}
+
//===----------------------------------------------------------------------===//
// Entry Points into this File
//===----------------------------------------------------------------------===//
@@ -1382,7 +1409,7 @@ void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
// Optimize the slot if possible.
CheckAggExprForMemSetUse(Slot, E, *this);
- AggExprEmitter(*this, Slot).Visit(const_cast<Expr*>(E));
+ AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr*>(E));
}
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
@@ -1408,7 +1435,8 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
assert((Record->hasTrivialCopyConstructor() ||
Record->hasTrivialCopyAssignment() ||
Record->hasTrivialMoveConstructor() ||
- Record->hasTrivialMoveAssignment()) &&
+ Record->hasTrivialMoveAssignment() ||
+ Record->isUnion()) &&
"Trying to aggregate-copy a type without a trivial copy/move "
"constructor or assignment operator");
// Ignore empty classes in C++.
@@ -1439,7 +1467,34 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
if (alignment.isZero())
alignment = TypeInfo.second;
- // FIXME: Handle variable sized types.
+ llvm::Value *SizeVal = nullptr;
+ if (TypeInfo.first.isZero()) {
+ // But note that getTypeInfo returns 0 for a VLA.
+ if (auto *VAT = dyn_cast_or_null<VariableArrayType>(
+ getContext().getAsArrayType(Ty))) {
+ QualType BaseEltTy;
+ SizeVal = emitArrayLength(VAT, BaseEltTy, DestPtr);
+ TypeInfo = getContext().getTypeInfoDataSizeInChars(BaseEltTy);
+ std::pair<CharUnits, CharUnits> LastElementTypeInfo;
+ if (!isAssignment)
+ LastElementTypeInfo = getContext().getTypeInfoInChars(BaseEltTy);
+ assert(!TypeInfo.first.isZero());
+ SizeVal = Builder.CreateNUWMul(
+ SizeVal,
+ llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
+ if (!isAssignment) {
+ SizeVal = Builder.CreateNUWSub(
+ SizeVal,
+ llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
+ SizeVal = Builder.CreateNUWAdd(
+ SizeVal, llvm::ConstantInt::get(
+ SizeTy, LastElementTypeInfo.first.getQuantity()));
+ }
+ }
+ }
+ if (!SizeVal) {
+ SizeVal = llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity());
+ }
// FIXME: If we have a volatile struct, the optimizer can remove what might
// appear to be `extra' memory ops:
@@ -1470,9 +1525,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
} else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
RecordDecl *Record = RecordTy->getDecl();
if (Record->hasObjectMember()) {
- CharUnits size = TypeInfo.first;
- llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
- llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity());
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;
@@ -1481,10 +1533,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
QualType BaseType = getContext().getBaseElementType(Ty);
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
if (RecordTy->getDecl()->hasObjectMember()) {
- CharUnits size = TypeInfo.first;
- llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
- llvm::Value *SizeVal =
- llvm::ConstantInt::get(SizeTy, size.getQuantity());
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;
@@ -1497,9 +1545,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
// the optimizer wishes to expand it in to scalar memory operations.
llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty);
- Builder.CreateMemCpy(DestPtr, SrcPtr,
- llvm::ConstantInt::get(IntPtrTy,
- TypeInfo.first.getQuantity()),
- alignment.getQuantity(), isVolatile,
- /*TBAATag=*/nullptr, TBAAStructTag);
+ Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, alignment.getQuantity(),
+ isVolatile, /*TBAATag=*/nullptr, TBAAStructTag);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
index 6d63b3a..c7adcca 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
@@ -173,7 +173,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
This = EmitLValue(Base).getAddress();
- if (MD->isTrivial()) {
+ if (MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion())) {
if (isa<CXXDestructorDecl>(MD)) return RValue::get(nullptr);
if (isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isDefaultConstructor())
@@ -254,8 +254,15 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
} else if (UseVirtualCall) {
- Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty);
+ Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty,
+ CE->getLocStart());
} else {
+ if (SanOpts.has(SanitizerKind::CFINVCall) &&
+ MD->getParent()->isDynamicClass()) {
+ llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy);
+ EmitVTablePtrCheckForCall(MD, VTable, CFITCK_NVCall, CE->getLocStart());
+ }
+
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod)
@@ -684,7 +691,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
llvm::Value *tsmV =
llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier);
llvm::Value *result =
- CGF.Builder.CreateCall2(umul_with_overflow, size, tsmV);
+ CGF.Builder.CreateCall(umul_with_overflow, {size, tsmV});
llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);
if (hasOverflow)
@@ -723,7 +730,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize);
llvm::Value *result =
- CGF.Builder.CreateCall2(uadd_with_overflow, size, cookieSizeV);
+ CGF.Builder.CreateCall(uadd_with_overflow, {size, cookieSizeV});
llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);
if (hasOverflow)
@@ -778,12 +785,10 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
llvm_unreachable("bad evaluation kind");
}
-void
-CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
- QualType ElementType,
- llvm::Value *BeginPtr,
- llvm::Value *NumElements,
- llvm::Value *AllocSizeWithoutCookie) {
+void CodeGenFunction::EmitNewArrayInitializer(
+ const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy,
+ llvm::Value *BeginPtr, llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
// If we have a type with trivial initialization and no initializer,
// there's nothing to do.
if (!E->hasInitializer())
@@ -809,7 +814,8 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>(
AllocType->getAsArrayTypeUnsafe())) {
unsigned AS = CurPtr->getType()->getPointerAddressSpace();
- llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(AS);
+ ElementTy = ConvertTypeForMem(AllocType);
+ llvm::Type *AllocPtrTy = ElementTy->getPointerTo(AS);
CurPtr = Builder.CreateBitCast(CurPtr, AllocPtrTy);
InitListElements *= getContext().getConstantArrayElementCount(CAT);
}
@@ -839,7 +845,8 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
// initialization loops.
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
ILE->getInit(i)->getType(), CurPtr);
- CurPtr = Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.exp.next");
+ CurPtr = Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1,
+ "array.exp.next");
}
// The remaining elements are filled with the array filler expression.
@@ -952,6 +959,25 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
if (ILE->getNumInits() == 0 && TryMemsetInitialization())
return;
+ // If we have a struct whose every field is value-initialized, we can
+ // usually use memset.
+ if (auto *ILE = dyn_cast<InitListExpr>(Init)) {
+ if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
+ if (RType->getDecl()->isStruct()) {
+ unsigned NumFields = 0;
+ for (auto *Field : RType->getDecl()->fields())
+ if (!Field->isUnnamedBitfield())
+ ++NumFields;
+ if (ILE->getNumInits() == NumFields)
+ for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)
+ if (!isa<ImplicitValueInitExpr>(ILE->getInit(i)))
+ --NumFields;
+ if (ILE->getNumInits() == NumFields && TryMemsetInitialization())
+ return;
+ }
+ }
+ }
+
// Create the loop blocks.
llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
llvm::BasicBlock *LoopBB = createBasicBlock("new.loop");
@@ -1000,7 +1026,7 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
// Advance to the next element by adjusting the pointer type as necessary.
llvm::Value *NextPtr =
- Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.next");
+ Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1, "array.next");
// Check whether we've gotten to the end of the array and, if so,
// exit the loop.
@@ -1012,13 +1038,12 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
}
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
- QualType ElementType,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
+ QualType ElementType, llvm::Type *ElementTy,
+ llvm::Value *NewPtr, llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
- ApplyDebugLocation DL(CGF, E->getStartLoc());
+ ApplyDebugLocation DL(CGF, E);
if (E->isArray())
- CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements,
+ CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr, NumElements,
AllocSizeWithoutCookie);
else if (const Expr *Init = E->getInitializer())
StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
@@ -1279,10 +1304,9 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// Emit a null check on the allocation result if the allocation
// function is allowed to return null (because it has a non-throwing
- // exception spec; for this part, we inline
- // CXXNewExpr::shouldNullCheckAllocation()) and we have an
+ // exception spec or is the reserved placement new) and we have an
// interesting initializer.
- bool nullCheck = allocatorType->isNothrow(getContext()) &&
+ bool nullCheck = E->shouldNullCheckAllocation(getContext()) &&
(!allocType.isPODType(getContext()) || E->hasInitializer());
llvm::BasicBlock *nullCheckBB = nullptr;
@@ -1327,11 +1351,11 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
E, allocType);
}
- llvm::Type *elementPtrTy
- = ConvertTypeForMem(allocType)->getPointerTo(AS);
+ llvm::Type *elementTy = ConvertTypeForMem(allocType);
+ llvm::Type *elementPtrTy = elementTy->getPointerTo(AS);
llvm::Value *result = Builder.CreateBitCast(allocation, elementPtrTy);
- EmitNewInitializer(*this, E, allocType, result, numElements,
+ EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
if (E->isArray()) {
// NewPtr is a pointer to the base element type. If we're
@@ -1524,7 +1548,8 @@ namespace {
// The size of an element, multiplied by the number of elements.
llvm::Value *Size
= llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity());
- Size = CGF.Builder.CreateMul(Size, NumElements);
+ if (NumElements)
+ Size = CGF.Builder.CreateMul(Size, NumElements);
// Plus the size of the cookie if applicable.
if (!CookieSize.isZero()) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
index 1580bbe..27d1c68 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
@@ -95,6 +95,7 @@ public:
//===--------------------------------------------------------------------===//
ComplexPairTy Visit(Expr *E) {
+ ApplyDebugLocation DL(CGF, E);
return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E);
}
@@ -316,14 +317,14 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
llvm::Value *Real=nullptr, *Imag=nullptr;
if (!IgnoreReal || isVolatile) {
- llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
+ llvm::Value *RealP = Builder.CreateStructGEP(nullptr, SrcPtr, 0,
SrcPtr->getName() + ".realp");
Real = Builder.CreateAlignedLoad(RealP, AlignR, isVolatile,
SrcPtr->getName() + ".real");
}
if (!IgnoreImag || isVolatile) {
- llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1,
+ llvm::Value *ImagP = Builder.CreateStructGEP(nullptr, SrcPtr, 1,
SrcPtr->getName() + ".imagp");
Imag = Builder.CreateAlignedLoad(ImagP, AlignI, isVolatile,
SrcPtr->getName() + ".imag");
@@ -335,12 +336,13 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
/// specified value pointer.
void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
bool isInit) {
- if (lvalue.getType()->isAtomicType())
+ if (lvalue.getType()->isAtomicType() ||
+ (!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue)))
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
llvm::Value *Ptr = lvalue.getAddress();
- llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
+ llvm::Value *RealPtr = Builder.CreateStructGEP(nullptr, Ptr, 0, "real");
+ llvm::Value *ImagPtr = Builder.CreateStructGEP(nullptr, Ptr, 1, "imag");
unsigned AlignR = lvalue.getAlignment().getQuantity();
ASTContext &C = CGF.getContext();
QualType ComplexTy = lvalue.getType();
@@ -375,7 +377,7 @@ VisitImaginaryLiteral(const ImaginaryLiteral *IL) {
ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
- if (E->getCallReturnType()->isReferenceType())
+ if (E->getCallReturnType(CGF.getContext())->isReferenceType())
return EmitLoadOfLValue(E);
return CGF.EmitCallExpr(E).getComplexVal();
@@ -818,6 +820,8 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
QualType LHSTy = E->getLHS()->getType();
+ if (const AtomicType *AT = LHSTy->getAs<AtomicType>())
+ LHSTy = AT->getValueType();
BinOpInfo OpInfo;
@@ -945,13 +949,14 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// Bind the common expression if necessary.
CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- RegionCounter Cnt = CGF.getPGORegionCounter(E);
+
CodeGenFunction::ConditionalEvaluation eval(CGF);
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, Cnt.getCount());
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock,
+ CGF.getProfileCount(E));
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
ComplexPairTy LHS = Visit(E->getTrueExpr());
LHSBlock = Builder.GetInsertBlock();
CGF.EmitBranch(ContBlock);
@@ -1033,7 +1038,7 @@ ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
"Invalid complex expression to emit");
return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
- .Visit(const_cast<Expr*>(E));
+ .Visit(const_cast<Expr *>(E));
}
void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
@@ -1085,8 +1090,8 @@ EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
}
LValue CodeGenFunction::
-EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
- llvm::Value *&Result) {
+EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result) {
CompoundFunc Op = getComplexOp(E->getOpcode());
RValue Val;
LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
index 54f7eee..a15c151 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
@@ -33,6 +33,7 @@ using namespace CodeGen;
//===----------------------------------------------------------------------===//
namespace {
+class ConstExprEmitter;
class ConstStructBuilder {
CodeGenModule &CGM;
CodeGenFunction *CGF;
@@ -42,6 +43,10 @@ class ConstStructBuilder {
CharUnits LLVMStructAlignment;
SmallVector<llvm::Constant *, 32> Elements;
public:
+ static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CFG,
+ ConstExprEmitter *Emitter,
+ llvm::ConstantStruct *Base,
+ InitListExpr *Updater);
static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
InitListExpr *ILE);
static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
@@ -68,6 +73,8 @@ private:
void ConvertStructToPacked();
bool Build(InitListExpr *ILE);
+ bool Build(ConstExprEmitter *Emitter, llvm::ConstantStruct *Base,
+ InitListExpr *Updater);
void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
llvm::Constant *Finalize(QualType Ty);
@@ -383,14 +390,19 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
if (!EltInit)
return false;
-
+
if (!Field->isBitField()) {
// Handle non-bitfield members.
AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
} else {
// Otherwise we have a bitfield.
- AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
- cast<llvm::ConstantInt>(EltInit));
+ if (auto *CI = dyn_cast<llvm::ConstantInt>(EltInit)) {
+ AppendBitField(*Field, Layout.getFieldOffset(FieldNo), CI);
+ } else {
+ // We are trying to initialize a bitfield with a non-trivial constant,
+ // this must require run-time code.
+ return false;
+ }
}
}
@@ -542,6 +554,17 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
CodeGenFunction *CGF,
+ ConstExprEmitter *Emitter,
+ llvm::ConstantStruct *Base,
+ InitListExpr *Updater) {
+ ConstStructBuilder Builder(CGM, CGF);
+ if (!Builder.Build(Emitter, Base, Updater))
+ return nullptr;
+ return Builder.Finalize(Updater->getType());
+}
+
+llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
+ CodeGenFunction *CGF,
InitListExpr *ILE) {
ConstStructBuilder Builder(CGM, CGF);
@@ -813,6 +836,82 @@ public:
return nullptr;
}
+ llvm::Constant *EmitDesignatedInitUpdater(llvm::Constant *Base,
+ InitListExpr *Updater) {
+ QualType ExprType = Updater->getType();
+
+ if (ExprType->isArrayType()) {
+ llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(ExprType));
+ llvm::Type *ElemType = AType->getElementType();
+
+ unsigned NumInitElements = Updater->getNumInits();
+ unsigned NumElements = AType->getNumElements();
+
+ std::vector<llvm::Constant *> Elts;
+ Elts.reserve(NumElements);
+
+ if (llvm::ConstantDataArray *DataArray =
+ dyn_cast<llvm::ConstantDataArray>(Base))
+ for (unsigned i = 0; i != NumElements; ++i)
+ Elts.push_back(DataArray->getElementAsConstant(i));
+ else if (llvm::ConstantArray *Array =
+ dyn_cast<llvm::ConstantArray>(Base))
+ for (unsigned i = 0; i != NumElements; ++i)
+ Elts.push_back(Array->getOperand(i));
+ else
+ return nullptr; // FIXME: other array types not implemented
+
+ llvm::Constant *fillC = nullptr;
+ if (Expr *filler = Updater->getArrayFiller())
+ if (!isa<NoInitExpr>(filler))
+ fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF);
+ bool RewriteType = (fillC && fillC->getType() != ElemType);
+
+ for (unsigned i = 0; i != NumElements; ++i) {
+ Expr *Init = nullptr;
+ if (i < NumInitElements)
+ Init = Updater->getInit(i);
+
+ if (!Init && fillC)
+ Elts[i] = fillC;
+ else if (!Init || isa<NoInitExpr>(Init))
+ ; // Do nothing.
+ else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init))
+ Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE);
+ else
+ Elts[i] = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
+
+ if (!Elts[i])
+ return nullptr;
+ RewriteType |= (Elts[i]->getType() != ElemType);
+ }
+
+ if (RewriteType) {
+ std::vector<llvm::Type *> Types;
+ Types.reserve(NumElements);
+ for (unsigned i = 0; i != NumElements; ++i)
+ Types.push_back(Elts[i]->getType());
+ llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
+ Types, true);
+ return llvm::ConstantStruct::get(SType, Elts);
+ }
+
+ return llvm::ConstantArray::get(AType, Elts);
+ }
+
+ if (ExprType->isRecordType())
+ return ConstStructBuilder::BuildStruct(CGM, CGF, this,
+ dyn_cast<llvm::ConstantStruct>(Base), Updater);
+
+ return nullptr;
+ }
+
+ llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+ return EmitDesignatedInitUpdater(
+ CGM.EmitConstantExpr(E->getBase(), E->getType(), CGF),
+ E->getUpdater());
+ }
+
llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
if (!E->getConstructor()->isTrivial())
return nullptr;
@@ -998,6 +1097,68 @@ public:
} // end anonymous namespace.
+bool ConstStructBuilder::Build(ConstExprEmitter *Emitter,
+ llvm::ConstantStruct *Base,
+ InitListExpr *Updater) {
+ assert(Base && "base expression should not be empty");
+
+ QualType ExprType = Updater->getType();
+ RecordDecl *RD = ExprType->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const llvm::StructLayout *BaseLayout = CGM.getDataLayout().getStructLayout(
+ Base->getType());
+ unsigned FieldNo = -1;
+ unsigned ElementNo = 0;
+
+ for (FieldDecl *Field : RD->fields()) {
+ ++FieldNo;
+
+ if (RD->isUnion() && Updater->getInitializedFieldInUnion() != Field)
+ continue;
+
+ // Skip anonymous bitfields.
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ llvm::Constant *EltInit = Base->getOperand(ElementNo);
+
+ // Bail out if the type of the ConstantStruct does not have the same layout
+ // as the type of the InitListExpr.
+ if (CGM.getTypes().ConvertType(Field->getType()) != EltInit->getType() ||
+ Layout.getFieldOffset(ElementNo) !=
+ BaseLayout->getElementOffsetInBits(ElementNo))
+ return false;
+
+ // Get the initializer. If we encounter an empty field or a NoInitExpr,
+ // we use values from the base expression.
+ Expr *Init = nullptr;
+ if (ElementNo < Updater->getNumInits())
+ Init = Updater->getInit(ElementNo);
+
+ if (!Init || isa<NoInitExpr>(Init))
+ ; // Do nothing.
+ else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init))
+ EltInit = Emitter->EmitDesignatedInitUpdater(EltInit, ChildILE);
+ else
+ EltInit = CGM.EmitConstantExpr(Init, Field->getType(), CGF);
+
+ ++ElementNo;
+
+ if (!EltInit)
+ return false;
+
+ if (!Field->isBitField())
+ AppendField(Field, Layout.getFieldOffset(FieldNo), EltInit);
+ else if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(EltInit))
+ AppendBitField(Field, Layout.getFieldOffset(FieldNo), CI);
+ else
+ // Initializing a bitfield with a non-trivial constant?
+ return false;
+ }
+
+ return true;
+}
+
llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
CodeGenFunction *CGF) {
// Make a quick check if variable can be default NULL initialized
@@ -1110,7 +1271,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
unsigned AS = C->getType()->getPointerAddressSpace();
llvm::Type *CharPtrTy = Int8Ty->getPointerTo(AS);
llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, CharPtrTy);
- Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
+ Casted = llvm::ConstantExpr::getGetElementPtr(Int8Ty, Casted, Offset);
C = llvm::ConstantExpr::getPointerCast(Casted, C->getType());
}
@@ -1291,7 +1452,7 @@ CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
// A member function pointer.
if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
- return getCXXABI().EmitMemberPointer(method);
+ return getCXXABI().EmitMemberFunctionPointer(method);
// Otherwise, a member data pointer.
uint64_t fieldOffset = getContext().getFieldOffset(decl);
@@ -1344,8 +1505,14 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
}
// For unions, stop after the first named field.
- if (record->isUnion() && Field->getDeclName())
- break;
+ if (record->isUnion()) {
+ if (Field->getIdentifier())
+ break;
+ if (const auto *FieldRD =
+ dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
+ if (FieldRD->findFirstNamedDataMember())
+ break;
+ }
}
// Fill in the virtual bases, if we're working with the complete object.
@@ -1403,10 +1570,6 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
llvm::Constant *Element = EmitNullConstant(ElementTy);
unsigned NumElements = CAT->getSize().getZExtValue();
-
- if (Element->isNullValue())
- return llvm::ConstantAggregateZero::get(ATy);
-
SmallVector<llvm::Constant *, 8> Array(NumElements, Element);
return llvm::ConstantArray::get(ATy, Array);
}
@@ -1416,8 +1579,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
return ::EmitNullConstant(*this, RD, /*complete object*/ true);
}
- assert(T->isMemberPointerType() && "Should only see member pointers here!");
- assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
+ assert(T->isMemberDataPointerType() &&
"Should only see pointers to data members here!");
return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>());
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
index 3be14c8..c73f118 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -16,6 +16,7 @@
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
+#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecordLayout.h"
@@ -85,7 +86,7 @@ public:
return CGF.EmitCheckedLValue(E, TCK);
}
- void EmitBinOpCheck(ArrayRef<std::pair<Value *, SanitizerKind>> Checks,
+ void EmitBinOpCheck(ArrayRef<std::pair<Value *, SanitizerMask>> Checks,
const BinOpInfo &Info);
Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
@@ -196,7 +197,7 @@ public:
//===--------------------------------------------------------------------===//
Value *Visit(Expr *E) {
- ApplyDebugLocation DL(CGF, E->getLocStart());
+ ApplyDebugLocation DL(CGF, E);
return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
}
@@ -320,7 +321,7 @@ public:
Value *VisitCastExpr(CastExpr *E);
Value *VisitCallExpr(const CallExpr *E) {
- if (E->getCallReturnType()->isReferenceType())
+ if (E->getCallReturnType(CGF.getContext())->isReferenceType())
return EmitLoadOfLValue(E);
Value *V = CGF.EmitCallExpr(E).getScalarVal();
@@ -349,10 +350,9 @@ public:
return EmitScalarPrePostIncDec(E, LV, true, true);
}
- llvm::Value *EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
- llvm::Value *InVal,
- llvm::Value *NextVal,
- bool IsInc);
+ llvm::Value *EmitIncDecConsiderOverflowBehavior(const UnaryOperator *E,
+ llvm::Value *InVal,
+ bool IsInc);
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
@@ -745,23 +745,37 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
QualType OrigSrcType = SrcType;
llvm::Type *SrcTy = Src->getType();
- // If casting to/from storage-only half FP, use special intrinsics.
- if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType &&
- !CGF.getContext().getLangOpts().HalfArgsAndReturns) {
- Src = Builder.CreateCall(
- CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
- CGF.CGM.FloatTy),
- Src);
- SrcType = CGF.getContext().FloatTy;
- SrcTy = CGF.FloatTy;
- }
-
// Handle conversions to bool first, they are special: comparisons against 0.
if (DstType->isBooleanType())
return EmitConversionToBool(Src, SrcType);
llvm::Type *DstTy = ConvertType(DstType);
+ // Cast from half through float if half isn't a native type.
+ if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
+ // Cast to FP using the intrinsic if the half type itself isn't supported.
+ if (DstTy->isFloatingPointTy()) {
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns)
+ return Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy),
+ Src);
+ } else {
+ // Cast to other types through float, using either the intrinsic or FPExt,
+ // depending on whether the half type itself is supported
+ // (as opposed to operations on half, available with NativeHalfType).
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ Src = Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
+ CGF.CGM.FloatTy),
+ Src);
+ } else {
+ Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
+ }
+ SrcType = CGF.getContext().FloatTy;
+ SrcTy = CGF.FloatTy;
+ }
+ }
+
// Ignore conversions like int -> uint.
if (SrcTy == DstTy)
return Src;
@@ -818,10 +832,20 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType,
DstTy);
- // Cast to half via float
- if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType &&
- !CGF.getContext().getLangOpts().HalfArgsAndReturns)
+ // Cast to half through float if half isn't a native type.
+ if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
+ // Make sure we cast in a single step if from another FP type.
+ if (SrcTy->isFloatingPointTy()) {
+ // Use the intrinsic if the half type itself isn't supported
+ // (as opposed to operations on half, available with NativeHalfType).
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns)
+ return Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src);
+ // If the half type is supported, just use an fptrunc.
+ return Builder.CreateFPTrunc(Src, DstTy);
+ }
DstTy = CGF.FloatTy;
+ }
if (isa<llvm::IntegerType>(SrcTy)) {
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
@@ -847,10 +871,14 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
}
if (DstTy != ResTy) {
- assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
- Res = Builder.CreateCall(
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
+ Res = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy),
Res);
+ } else {
+ Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
+ }
}
return Res;
@@ -889,7 +917,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
/// operation). The check passes if all values in \p Checks (which are \c i1),
/// are \c true.
void ScalarExprEmitter::EmitBinOpCheck(
- ArrayRef<std::pair<Value *, SanitizerKind>> Checks, const BinOpInfo &Info) {
+ ArrayRef<std::pair<Value *, SanitizerMask>> Checks, const BinOpInfo &Info) {
assert(CGF.IsSanitizerScope);
StringRef CheckName;
SmallVector<llvm::Constant *, 4> StaticData;
@@ -1355,6 +1383,15 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
llvm_unreachable("wrong cast for pointers in different address spaces"
"(must be an address space cast)!");
}
+
+ if (CGF.SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+ if (auto PT = DestTy->getAs<PointerType>())
+ CGF.EmitVTablePtrCheckForCast(PT->getPointeeType(), Src,
+ /*MayBeNull=*/true,
+ CodeGenFunction::CFITCK_UnrelatedCast,
+ CE->getLocStart());
+ }
+
return Builder.CreateBitCast(Src, DstTy);
}
case CK_AddressSpaceConversion: {
@@ -1384,6 +1421,12 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
Derived, DestTy->getPointeeType());
+ if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast))
+ CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived,
+ /*MayBeNull=*/true,
+ CodeGenFunction::CFITCK_DerivedCast,
+ CE->getLocStart());
+
return Derived;
}
case CK_UncheckedDerivedToBase:
@@ -1412,13 +1455,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
// anything here.
if (!E->getType()->isVariableArrayType()) {
assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
+ llvm::Type *NewTy = ConvertType(E->getType());
V = CGF.Builder.CreatePointerCast(
- V, ConvertType(E->getType())->getPointerTo(
- V->getType()->getPointerAddressSpace()));
+ V, NewTy->getPointerTo(V->getType()->getPointerAddressSpace()));
assert(isa<llvm::ArrayType>(V->getType()->getPointerElementType()) &&
"Expected pointer to array");
- V = Builder.CreateStructGEP(V, 0, "arraydecay");
+ V = Builder.CreateStructGEP(NewTy, V, 0, "arraydecay");
}
// Make sure the array decay ends up being the right type. This matters if
@@ -1571,26 +1614,32 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
// Unary Operators
//===----------------------------------------------------------------------===//
-llvm::Value *ScalarExprEmitter::
-EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
- llvm::Value *InVal,
- llvm::Value *NextVal, bool IsInc) {
+static BinOpInfo createBinOpInfoFromIncDec(const UnaryOperator *E,
+ llvm::Value *InVal, bool IsInc) {
+ BinOpInfo BinOp;
+ BinOp.LHS = InVal;
+ BinOp.RHS = llvm::ConstantInt::get(InVal->getType(), 1, false);
+ BinOp.Ty = E->getType();
+ BinOp.Opcode = IsInc ? BO_Add : BO_Sub;
+ BinOp.FPContractable = false;
+ BinOp.E = E;
+ return BinOp;
+}
+
+llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
+ const UnaryOperator *E, llvm::Value *InVal, bool IsInc) {
+ llvm::Value *Amount =
+ llvm::ConstantInt::get(InVal->getType(), IsInc ? 1 : -1, true);
+ StringRef Name = IsInc ? "inc" : "dec";
switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
case LangOptions::SOB_Defined:
- return Builder.CreateAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+ return Builder.CreateAdd(InVal, Amount, Name);
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
- return Builder.CreateNSWAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+ return Builder.CreateNSWAdd(InVal, Amount, Name);
// Fall through.
case LangOptions::SOB_Trapping:
- BinOpInfo BinOp;
- BinOp.LHS = InVal;
- BinOp.RHS = NextVal;
- BinOp.Ty = E->getType();
- BinOp.Opcode = BO_Add;
- BinOp.FPContractable = false;
- BinOp.E = E;
- return EmitOverflowCheckedBinOp(BinOp);
+ return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc));
}
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
}
@@ -1668,27 +1717,20 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// Most common case by far: integer increment.
} else if (type->isIntegerType()) {
-
- llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
-
// Note that signed integer inc/dec with width less than int can't
// overflow because of promotion rules; we're just eliding a few steps here.
bool CanOverflow = value->getType()->getIntegerBitWidth() >=
CGF.IntTy->getIntegerBitWidth();
if (CanOverflow && type->isSignedIntegerOrEnumerationType()) {
- value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
+ value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
} else if (CanOverflow && type->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
- BinOpInfo BinOp;
- BinOp.LHS = value;
- BinOp.RHS = llvm::ConstantInt::get(value->getType(), 1, false);
- BinOp.Ty = E->getType();
- BinOp.Opcode = isInc ? BO_Add : BO_Sub;
- BinOp.FPContractable = false;
- BinOp.E = E;
- value = EmitOverflowCheckedBinOp(BinOp);
- } else
+ value =
+ EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc));
+ } else {
+ llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
+ }
// Next most common: pointer increment.
} else if (const PointerType *ptr = type->getAs<PointerType>()) {
@@ -1742,13 +1784,16 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// Add the inc/dec to the real part.
llvm::Value *amt;
- if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType &&
- !CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
// Another special case: half FP increment should be done via float
- value = Builder.CreateCall(
- CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
- CGF.CGM.FloatTy),
- input);
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ value = Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
+ CGF.CGM.FloatTy),
+ input, "incdec.conv");
+ } else {
+ value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv");
+ }
}
if (value->getType()->isFloatTy())
@@ -1758,20 +1803,29 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
amt = llvm::ConstantFP::get(VMContext,
llvm::APFloat(static_cast<double>(amount)));
else {
+ // Remaining types are either Half or LongDouble. Convert from float.
llvm::APFloat F(static_cast<float>(amount));
bool ignored;
- F.convert(CGF.getTarget().getLongDoubleFormat(),
+ // Don't use getFloatTypeSemantics because Half isn't
+ // necessarily represented using the "half" LLVM type.
+ F.convert(value->getType()->isHalfTy()
+ ? CGF.getTarget().getHalfFormat()
+ : CGF.getTarget().getLongDoubleFormat(),
llvm::APFloat::rmTowardZero, &ignored);
amt = llvm::ConstantFP::get(VMContext, F);
}
value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
- if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType &&
- !CGF.getContext().getLangOpts().HalfArgsAndReturns)
- value = Builder.CreateCall(
- CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16,
- CGF.CGM.FloatTy),
- value);
+ if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
+ if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ value = Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16,
+ CGF.CGM.FloatTy),
+ value, "incdec.conv");
+ } else {
+ value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv");
+ }
+ }
// Objective-C pointer types.
} else {
@@ -1794,10 +1848,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
auto Pair = CGF.EmitAtomicCompareExchange(
- LV, RValue::get(atomicPHI), RValue::get(CGF.EmitToMemory(value, type)),
- E->getExprLoc());
- llvm::Value *old = Pair.first.getScalarVal();
- llvm::Value *success = Pair.second.getScalarVal();
+ LV, RValue::get(atomicPHI), RValue::get(value), E->getExprLoc());
+ llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), type);
+ llvm::Value *success = Pair.second;
atomicPHI->addIncoming(old, opBB);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
@@ -1985,6 +2038,13 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
return size;
}
+ } else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) {
+ auto Alignment =
+ CGF.getContext()
+ .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
+ E->getTypeOfArgument()->getPointeeType()))
+ .getQuantity();
+ return llvm::ConstantInt::get(CGF.SizeTy, Alignment);
}
// If this isn't sizeof(vla), the result must be constant; use the constant
@@ -2056,7 +2116,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
BinOpInfo OpInfo;
if (E->getComputationResultType()->isAnyComplexType())
- return CGF.EmitScalarCompooundAssignWithComplex(E, Result);
+ return CGF.EmitScalarCompoundAssignWithComplex(E, Result);
// Emit the RHS first. __block variables need to have the rhs evaluated
// first, plus this should improve codegen a little.
@@ -2138,10 +2198,9 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
auto Pair = CGF.EmitAtomicCompareExchange(
- LHSLV, RValue::get(atomicPHI),
- RValue::get(CGF.EmitToMemory(Result, LHSTy)), E->getExprLoc());
- llvm::Value *old = Pair.first.getScalarVal();
- llvm::Value *success = Pair.second.getScalarVal();
+ LHSLV, RValue::get(atomicPHI), RValue::get(Result), E->getExprLoc());
+ llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), LHSTy);
+ llvm::Value *success = Pair.second;
atomicPHI->addIncoming(old, opBB);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
@@ -2184,7 +2243,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
- SmallVector<std::pair<llvm::Value *, SanitizerKind>, 2> Checks;
+ SmallVector<std::pair<llvm::Value *, SanitizerMask>, 2> Checks;
if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -2296,7 +2355,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
llvm::Function *intrinsic = CGF.CGM.getIntrinsic(IID, opTy);
- Value *resultAndOverflow = Builder.CreateCall2(intrinsic, Ops.LHS, Ops.RHS);
+ Value *resultAndOverflow = Builder.CreateCall(intrinsic, {Ops.LHS, Ops.RHS});
Value *result = Builder.CreateExtractValue(resultAndOverflow, 0);
Value *overflow = Builder.CreateExtractValue(resultAndOverflow, 1);
@@ -2309,7 +2368,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *NotOverflow = Builder.CreateNot(overflow);
- SanitizerKind Kind = isSigned ? SanitizerKind::SignedIntegerOverflow
+ SanitizerMask Kind = isSigned ? SanitizerKind::SignedIntegerOverflow
: SanitizerKind::UnsignedIntegerOverflow;
EmitBinOpCheck(std::make_pair(NotOverflow, Kind), Ops);
} else
@@ -2476,10 +2535,9 @@ static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend,
"neg");
}
- Value *FMulAdd =
- Builder.CreateCall3(
+ Value *FMulAdd = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()),
- MulOp0, MulOp1, Addend);
+ {MulOp0, MulOp1, Addend});
MulOp->eraseFromParent();
return FMulAdd;
@@ -2664,21 +2722,34 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
if (Ops.LHS->getType() != RHS->getType())
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
- if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
- isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ bool SanitizeBase = CGF.SanOpts.has(SanitizerKind::ShiftBase) &&
+ Ops.Ty->hasSignedIntegerRepresentation();
+ bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent);
+ // OpenCL 6.3j: shift values are effectively % word size of LHS.
+ if (CGF.getLangOpts().OpenCL)
+ RHS =
+ Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask");
+ else if ((SanitizeBase || SanitizeExponent) &&
+ isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SmallVector<std::pair<Value *, SanitizerMask>, 2> Checks;
llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
- llvm::Value *Valid = Builder.CreateICmpULE(RHS, WidthMinusOne);
+ llvm::Value *ValidExponent = Builder.CreateICmpULE(RHS, WidthMinusOne);
- if (Ops.Ty->hasSignedIntegerRepresentation()) {
- llvm::BasicBlock *Orig = Builder.GetInsertBlock();
- llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
- llvm::BasicBlock *CheckBitsShifted = CGF.createBasicBlock("check");
- Builder.CreateCondBr(Valid, CheckBitsShifted, Cont);
+ if (SanitizeExponent) {
+ Checks.push_back(
+ std::make_pair(ValidExponent, SanitizerKind::ShiftExponent));
+ }
+ if (SanitizeBase) {
// Check whether we are shifting any non-zero bits off the top of the
- // integer.
- CGF.EmitBlock(CheckBitsShifted);
+ // integer. We only emit this check if exponent is valid - otherwise
+ // instructions below will have undefined behavior themselves.
+ llvm::BasicBlock *Orig = Builder.GetInsertBlock();
+ llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
+ llvm::BasicBlock *CheckShiftBase = CGF.createBasicBlock("check");
+ Builder.CreateCondBr(ValidExponent, CheckShiftBase, Cont);
+ CGF.EmitBlock(CheckShiftBase);
llvm::Value *BitsShiftedOff =
Builder.CreateLShr(Ops.LHS,
Builder.CreateSub(WidthMinusOne, RHS, "shl.zeros",
@@ -2693,19 +2764,17 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
BitsShiftedOff = Builder.CreateLShr(BitsShiftedOff, One);
}
llvm::Value *Zero = llvm::ConstantInt::get(BitsShiftedOff->getType(), 0);
- llvm::Value *SecondCheck = Builder.CreateICmpEQ(BitsShiftedOff, Zero);
+ llvm::Value *ValidBase = Builder.CreateICmpEQ(BitsShiftedOff, Zero);
CGF.EmitBlock(Cont);
- llvm::PHINode *P = Builder.CreatePHI(Valid->getType(), 2);
- P->addIncoming(Valid, Orig);
- P->addIncoming(SecondCheck, CheckBitsShifted);
- Valid = P;
+ llvm::PHINode *BaseCheck = Builder.CreatePHI(ValidBase->getType(), 2);
+ BaseCheck->addIncoming(Builder.getTrue(), Orig);
+ BaseCheck->addIncoming(ValidBase, CheckShiftBase);
+ Checks.push_back(std::make_pair(BaseCheck, SanitizerKind::ShiftBase));
}
- EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::Shift), Ops);
+ assert(!Checks.empty());
+ EmitBinOpCheck(Checks, Ops);
}
- // OpenCL 6.3j: shift values are effectively % word size of LHS.
- if (CGF.getLangOpts().OpenCL)
- RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask");
return Builder.CreateShl(Ops.LHS, RHS, "shl");
}
@@ -2717,18 +2786,18 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
if (Ops.LHS->getType() != RHS->getType())
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
- if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
- isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ // OpenCL 6.3j: shift values are effectively % word size of LHS.
+ if (CGF.getLangOpts().OpenCL)
+ RHS =
+ Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask");
+ else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
+ isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *Valid =
Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS));
- EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::Shift), Ops);
+ EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::ShiftExponent), Ops);
}
- // OpenCL 6.3j: shift values are effectively % word size of LHS.
- if (CGF.getLangOpts().OpenCL)
- RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask");
-
if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateLShr(Ops.LHS, RHS, "shr");
return Builder.CreateAShr(Ops.LHS, RHS, "shr");
@@ -2846,7 +2915,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
Value *CR6Param = Builder.getInt32(CR6);
llvm::Function *F = CGF.CGM.getIntrinsic(ID);
- Result = Builder.CreateCall3(F, CR6Param, FirstVecArg, SecondVecArg, "");
+ Result = Builder.CreateCall(F, {CR6Param, FirstVecArg, SecondVecArg});
return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
}
@@ -2975,11 +3044,9 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
- RegionCounter Cnt = CGF.getPGORegionCounter(E);
-
// Perform vector logical and on comparisons with zero vectors.
if (E->getType()->isVectorType()) {
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());
@@ -3002,7 +3069,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
bool LHSCondVal;
if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) {
if (LHSCondVal) { // If we have 1 && X, just emit X.
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
// ZExt result to int or bool.
@@ -3020,7 +3087,8 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
CodeGenFunction::ConditionalEvaluation eval(CGF);
// Branch on the LHS first. If it is false, go to the failure (cont) block.
- CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, ContBlock, Cnt.getCount());
+ CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, ContBlock,
+ CGF.getProfileCount(E->getRHS()));
// Any edges into the ContBlock are now from an (indeterminate number of)
// edges from this first condition. All of these values will be false. Start
@@ -3033,7 +3101,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
eval.end(CGF);
@@ -3043,7 +3111,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
// Emit an unconditional branch from this block to ContBlock.
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
+ auto NL = ApplyDebugLocation::CreateEmpty(CGF);
CGF.EmitBlock(ContBlock);
}
// Insert an entry into the phi node for the edge with the value of RHSCond.
@@ -3054,11 +3122,9 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
}
Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
- RegionCounter Cnt = CGF.getPGORegionCounter(E);
-
// Perform vector logical or on comparisons with zero vectors.
if (E->getType()->isVectorType()) {
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());
@@ -3081,7 +3147,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
bool LHSCondVal;
if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) {
if (!LHSCondVal) { // If we have 0 || X, just emit X.
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
// ZExt result to int or bool.
@@ -3100,7 +3166,8 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
// Branch on the LHS first. If it is true, go to the success (cont) block.
CGF.EmitBranchOnBoolExpr(E->getLHS(), ContBlock, RHSBlock,
- Cnt.getParentCount() - Cnt.getCount());
+ CGF.getCurrentProfileCount() -
+ CGF.getProfileCount(E->getRHS()));
// Any edges into the ContBlock are now from an (indeterminate number of)
// edges from this first condition. All of these values will be true. Start
@@ -3115,7 +3182,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
// Emit the RHS condition as a bool value.
CGF.EmitBlock(RHSBlock);
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
eval.end(CGF);
@@ -3166,7 +3233,6 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// Bind the common expression if necessary.
CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- RegionCounter Cnt = CGF.getPGORegionCounter(E);
Expr *condExpr = E->getCond();
Expr *lhsExpr = E->getTrueExpr();
@@ -3182,7 +3248,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// If the dead side doesn't have labels we need, just emit the Live part.
if (!CGF.ContainsLabel(dead)) {
if (CondExprBool)
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
Value *Result = Visit(live);
// If the live part is a throw expression, it acts like it has a void
@@ -3199,7 +3265,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// the select function.
if (CGF.getLangOpts().OpenCL
&& condExpr->getType()->isVectorType()) {
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
llvm::Value *CondV = CGF.EmitScalarExpr(condExpr);
llvm::Value *LHS = Visit(lhsExpr);
@@ -3244,7 +3310,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// safe to evaluate the LHS and RHS unconditionally.
if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) &&
isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) {
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
llvm::Value *LHS = Visit(lhsExpr);
@@ -3262,10 +3328,11 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
CodeGenFunction::ConditionalEvaluation eval(CGF);
- CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock, Cnt.getCount());
+ CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock,
+ CGF.getProfileCount(lhsExpr));
CGF.EmitBlock(LHSBlock);
- Cnt.beginRegion(Builder);
+ CGF.incrementProfileCounter(E);
eval.begin(CGF);
Value *LHS = Visit(lhsExpr);
eval.end(CGF);
@@ -3393,14 +3460,8 @@ Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
assert(E && hasScalarEvaluationKind(E->getType()) &&
"Invalid scalar expression to emit");
- bool hasDebugInfo = getDebugInfo();
- if (isa<CXXDefaultArgExpr>(E))
- disableDebugInfo();
- Value *V = ScalarExprEmitter(*this, IgnoreResultAssign)
- .Visit(const_cast<Expr*>(E));
- if (isa<CXXDefaultArgExpr>(E) && hasDebugInfo)
- enableDebugInfo();
- return V;
+ return ScalarExprEmitter(*this, IgnoreResultAssign)
+ .Visit(const_cast<Expr *>(E));
}
/// EmitScalarConversion - Emit a conversion from the specified type to the
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
index 89f43c2..1163d63 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -8,13 +8,14 @@
//===----------------------------------------------------------------------===//
#include "CGLoopInfo.h"
+#include "clang/AST/Attr.h"
+#include "clang/Sema/LoopHint.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
-using namespace clang;
-using namespace CodeGen;
+using namespace clang::CodeGen;
using namespace llvm;
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
@@ -26,8 +27,8 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
SmallVector<Metadata *, 4> Args;
// Reserve operand 0 for loop id self reference.
- MDNode *TempNode = MDNode::getTemporary(Ctx, None);
- Args.push_back(TempNode);
+ auto TempNode = MDNode::getTemporary(Ctx, None);
+ Args.push_back(TempNode.get());
// Setting vectorizer.width
if (Attrs.VectorizerWidth > 0) {
@@ -58,7 +59,6 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
// Set the first operand to itself.
MDNode *LoopID = MDNode::get(Ctx, Args);
LoopID->replaceOperandWith(0, LoopID);
- MDNode::deleteTemporary(TempNode);
return LoopID;
}
@@ -78,7 +78,34 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
LoopID = createMetadata(Header->getContext(), Attrs);
}
-void LoopInfoStack::push(BasicBlock *Header) {
+void LoopInfoStack::push(BasicBlock *Header,
+ ArrayRef<const clang::Attr *> Attrs) {
+ for (const auto *Attr : Attrs) {
+ const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
+
+ // Skip non loop hint attributes
+ if (!LH)
+ continue;
+
+ LoopHintAttr::OptionType Option = LH->getOption();
+ LoopHintAttr::LoopHintState State = LH->getState();
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ if (State == LoopHintAttr::AssumeSafety) {
+ // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
+ setParallel(true);
+ }
+ break;
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollCount:
+ // Nothing to do here for these loop hints.
+ break;
+ }
+ }
+
Active.push_back(LoopInfo(Header, StagedAttrs));
// Clear the attributes so nested loops do not inherit them.
StagedAttrs.clear();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
index b169399..2249937 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
#define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Value.h"
@@ -27,6 +28,7 @@ class MDNode;
} // end namespace llvm
namespace clang {
+class Attr;
namespace CodeGen {
/// \brief Attributes that may be specified on loops.
@@ -78,15 +80,16 @@ private:
/// This stack can be used to prepare attributes which are applied when a loop
/// is emitted.
class LoopInfoStack {
- LoopInfoStack(const LoopInfoStack &) LLVM_DELETED_FUNCTION;
- void operator=(const LoopInfoStack &) LLVM_DELETED_FUNCTION;
+ LoopInfoStack(const LoopInfoStack &) = delete;
+ void operator=(const LoopInfoStack &) = delete;
public:
LoopInfoStack() {}
/// \brief Begin a new structured loop. The set of staged attributes will be
/// applied to the loop and then cleared.
- void push(llvm::BasicBlock *Header);
+ void push(llvm::BasicBlock *Header,
+ llvm::ArrayRef<const Attr *> Attrs = llvm::None);
/// \brief End the current loop.
void pop();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index 34c6d94..eb76ad1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/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.
@@ -55,13 +54,15 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
/// EmitObjCBoxedExpr - This routine generates code to call
/// the appropriate expression boxing method. This will either be
-/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:].
+/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:],
+/// or [NSValue valueWithBytes:objCType:].
///
llvm::Value *
CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
// Generate the correct selector for this literal's concrete type.
// Get the method.
const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod();
+ const Expr *SubExpr = E->getSubExpr();
assert(BoxingMethod && "BoxingMethod is null");
assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method");
Selector Sel = BoxingMethod->getSelector();
@@ -74,7 +75,35 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl);
CallArgList Args;
- EmitCallArgs(Args, BoxingMethod, E->arg_begin(), E->arg_end());
+ const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin();
+ QualType ArgQT = ArgDecl->getType().getUnqualifiedType();
+
+ // ObjCBoxedExpr supports boxing of structs and unions
+ // via [NSValue valueWithBytes:objCType:]
+ const QualType ValueType(SubExpr->getType().getCanonicalType());
+ if (ValueType->isObjCBoxableRecordType()) {
+ // Emit CodeGen for first parameter
+ // and cast value to correct type
+ llvm::Value *Temporary = CreateMemTemp(SubExpr->getType());
+ EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true);
+ llvm::Value *BitCast = Builder.CreateBitCast(Temporary,
+ ConvertType(ArgQT));
+ Args.add(RValue::get(BitCast), ArgQT);
+
+ // Create char array to store type encoding
+ std::string Str;
+ getContext().getObjCEncodingForType(ValueType, Str);
+ llvm::GlobalVariable *GV = CGM.GetAddrOfConstantCString(Str);
+
+ // Cast type encoding to correct type
+ const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1];
+ QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType();
+ llvm::Value *Cast = Builder.CreateBitCast(GV, ConvertType(EncodingQT));
+
+ Args.add(RValue::get(Cast), EncodingQT);
+ } else {
+ Args.add(EmitAnyExpr(SubExpr), ArgQT);
+ }
RValue result = Runtime.GenerateMessageSend(
*this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver,
@@ -102,8 +131,8 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
- llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects");
- llvm::Value *Keys = nullptr;
+ llvm::AllocaInst *Objects = CreateMemTemp(ElementArrayType, "objects");
+ llvm::AllocaInst *Keys = nullptr;
if (DLE)
Keys = CreateMemTemp(ElementArrayType, "keys");
@@ -119,10 +148,9 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
if (ALE) {
// Emit the element and store it to the appropriate array slot.
const Expr *Rhs = ALE->getElement(i);
- LValue LV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
- ElementType,
- Context.getTypeAlignInChars(Rhs->getType()),
- Context);
+ LValue LV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
+ ElementType, Context.getTypeAlignInChars(Rhs->getType()), Context);
llvm::Value *value = EmitScalarExpr(Rhs);
EmitStoreThroughLValue(RValue::get(value), LV, true);
@@ -132,19 +160,17 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
} else {
// Emit the key and store it to the appropriate array slot.
const Expr *Key = DLE->getKeyValueElement(i).Key;
- LValue KeyLV = LValue::MakeAddr(Builder.CreateStructGEP(Keys, i),
- ElementType,
- Context.getTypeAlignInChars(Key->getType()),
- Context);
+ LValue KeyLV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Keys->getAllocatedType(), Keys, i),
+ ElementType, Context.getTypeAlignInChars(Key->getType()), Context);
llvm::Value *keyValue = EmitScalarExpr(Key);
EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true);
// Emit the value and store it to the appropriate array slot.
- const Expr *Value = DLE->getKeyValueElement(i).Value;
- LValue ValueLV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i),
- ElementType,
- Context.getTypeAlignInChars(Value->getType()),
- Context);
+ const Expr *Value = DLE->getKeyValueElement(i).Value;
+ LValue ValueLV = LValue::MakeAddr(
+ Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
+ ElementType, Context.getTypeAlignInChars(Value->getType()), Context);
llvm::Value *valueValue = EmitScalarExpr(Value);
EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true);
if (TrackNeededObjects) {
@@ -221,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
@@ -422,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 {
@@ -472,8 +497,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
args.push_back(OMD->getSelfDecl());
args.push_back(OMD->getCmdDecl());
- for (const auto *PI : OMD->params())
- args.push_back(PI);
+ args.append(OMD->param_begin(), OMD->param_end());
CurGD = OMD;
CurEHLocation = OMD->getLocEnd();
@@ -501,8 +525,7 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
StartObjCMethod(OMD, OMD->getClassInterface());
PGO.assignRegionCounters(OMD, CurFn);
assert(isa<CompoundStmt>(OMD->getBody()));
- RegionCounter Cnt = getPGORegionCounter(OMD->getBody());
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(OMD->getBody());
EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody()));
FinishFunction(OMD->getBodyRBrace());
}
@@ -1435,7 +1458,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fast enumeration state.
QualType StateTy = CGM.getObjCFastEnumerationStateType();
- llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
+ llvm::AllocaInst *StatePtr = CreateMemTemp(StateTy, "state.ptr");
EmitNullInitialization(StatePtr, StateTy);
// Number of elements in the items array.
@@ -1507,11 +1530,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// If the limit pointer was zero to begin with, the collection is
// empty; skip all this. Set the branch weight assuming this has the same
// probability of exiting the loop as any other loop exit.
- uint64_t EntryCount = PGO.getCurrentRegionCount();
- RegionCounter Cnt = getPGORegionCounter(&S);
- Builder.CreateCondBr(Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"),
- EmptyBB, LoopInitBB,
- PGO.createBranchWeights(EntryCount, Cnt.getCount()));
+ uint64_t EntryCount = getCurrentProfileCount();
+ Builder.CreateCondBr(
+ Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"), EmptyBB,
+ LoopInitBB,
+ createProfileWeights(EntryCount, getProfileCount(S.getBody())));
// Otherwise, initialize the loop.
EmitBlock(LoopInitBB);
@@ -1519,8 +1542,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Save the initial mutations value. This is the value at an
// address that was written into the state object by
// countByEnumeratingWithState:objects:count:.
- llvm::Value *StateMutationsPtrPtr =
- Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
+ llvm::Value *StateMutationsPtrPtr = Builder.CreateStructGEP(
+ StatePtr->getAllocatedType(), StatePtr, 2, "mutationsptr.ptr");
llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
"mutationsptr");
@@ -1540,7 +1563,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.count");
count->addIncoming(initialBufferLimit, LoopInitBB);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
// Check whether the mutations value has changed from where it was
// at start. StateMutationsPtr should actually be invariant between
@@ -1600,8 +1623,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fetch the buffer out of the enumeration state.
// TODO: this pointer should actually be invariant between
// refreshes, which would help us do certain loop optimizations.
- llvm::Value *StateItemsPtr =
- Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
+ llvm::Value *StateItemsPtr = Builder.CreateStructGEP(
+ StatePtr->getAllocatedType(), StatePtr, 1, "stateitems.ptr");
llvm::Value *EnumStateItems =
Builder.CreateLoad(StateItemsPtr, "stateitems");
@@ -1652,9 +1675,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Set the branch weights based on the simplifying assumption that this is
// like a while-loop, i.e., ignoring that the false branch fetches more
// elements and then returns to the loop.
- Builder.CreateCondBr(Builder.CreateICmpULT(indexPlusOne, count),
- LoopBodyBB, FetchMoreBB,
- PGO.createBranchWeights(Cnt.getCount(), EntryCount));
+ Builder.CreateCondBr(
+ Builder.CreateICmpULT(indexPlusOne, count), LoopBodyBB, FetchMoreBB,
+ createProfileWeights(getProfileCount(S.getBody()), EntryCount));
index->addIncoming(indexPlusOne, AfterBody.getBlock());
count->addIncoming(count, AfterBody.getBlock());
@@ -1985,7 +2008,8 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
}
// Call the marker asm if we made one, which we do only at -O0.
- if (marker) Builder.CreateCall(marker);
+ if (marker)
+ Builder.CreateCall(marker);
return emitARCValueOperation(*this, value,
CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue,
@@ -3000,13 +3024,9 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
SmallVector<Expr*, 4> ConstructorArgs;
ConstructorArgs.push_back(&SRC);
- CXXConstructExpr::arg_iterator A = CXXConstExpr->arg_begin();
- ++A;
-
- for (CXXConstructExpr::arg_iterator AEnd = CXXConstExpr->arg_end();
- A != AEnd; ++A)
- ConstructorArgs.push_back(*A);
-
+ ConstructorArgs.append(std::next(CXXConstExpr->arg_begin()),
+ CXXConstExpr->arg_end());
+
CXXConstructExpr *TheCXXConstructExpr =
CXXConstructExpr::Create(C, Ty, SourceLocation(),
CXXConstExpr->getConstructor(),
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index c0dc3b8..b52d623 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -46,54 +46,49 @@ namespace {
/// avoids constructing the type more than once if it's used more than once.
class LazyRuntimeFunction {
CodeGenModule *CGM;
- std::vector<llvm::Type*> ArgTys;
+ llvm::FunctionType *FTy;
const char *FunctionName;
llvm::Constant *Function;
- public:
- /// Constructor leaves this class uninitialized, because it is intended to
- /// be used as a field in another class and not all of the types that are
- /// used as arguments will necessarily be available at construction time.
- LazyRuntimeFunction()
- : CGM(nullptr), FunctionName(nullptr), Function(nullptr) {}
- /// Initialises the lazy function with the name, return type, and the types
- /// of the arguments.
- LLVM_END_WITH_NULL
- void init(CodeGenModule *Mod, const char *name,
- llvm::Type *RetTy, ...) {
- CGM =Mod;
- FunctionName = name;
- Function = nullptr;
- ArgTys.clear();
- va_list Args;
- va_start(Args, RetTy);
- while (llvm::Type *ArgTy = va_arg(Args, llvm::Type*))
- ArgTys.push_back(ArgTy);
- va_end(Args);
- // Push the return type on at the end so we can pop it off easily
- ArgTys.push_back(RetTy);
- }
- /// Overloaded cast operator, allows the class to be implicitly cast to an
- /// LLVM constant.
- operator llvm::Constant*() {
- if (!Function) {
- if (!FunctionName) return nullptr;
- // We put the return type on the end of the vector, so pop it back off
- llvm::Type *RetTy = ArgTys.back();
- ArgTys.pop_back();
- llvm::FunctionType *FTy = llvm::FunctionType::get(RetTy, ArgTys, false);
- Function =
- cast<llvm::Constant>(CGM->CreateRuntimeFunction(FTy, FunctionName));
- // We won't need to use the types again, so we may as well clean up the
- // vector now
- ArgTys.resize(0);
- }
- return Function;
- }
- operator llvm::Function*() {
- return cast<llvm::Function>((llvm::Constant*)*this);
- }
+public:
+ /// Constructor leaves this class uninitialized, because it is intended to
+ /// be used as a field in another class and not all of the types that are
+ /// used as arguments will necessarily be available at construction time.
+ LazyRuntimeFunction()
+ : CGM(nullptr), FunctionName(nullptr), Function(nullptr) {}
+ /// Initialises the lazy function with the name, return type, and the types
+ /// of the arguments.
+ LLVM_END_WITH_NULL
+ void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy, ...) {
+ CGM = Mod;
+ FunctionName = name;
+ Function = nullptr;
+ std::vector<llvm::Type *> ArgTys;
+ va_list Args;
+ va_start(Args, RetTy);
+ while (llvm::Type *ArgTy = va_arg(Args, llvm::Type *))
+ ArgTys.push_back(ArgTy);
+ va_end(Args);
+ FTy = llvm::FunctionType::get(RetTy, ArgTys, false);
+ }
+
+ llvm::FunctionType *getType() { return FTy; }
+
+ /// Overloaded cast operator, allows the class to be implicitly cast to an
+ /// LLVM constant.
+ operator llvm::Constant *() {
+ if (!Function) {
+ if (!FunctionName)
+ return nullptr;
+ Function =
+ cast<llvm::Constant>(CGM->CreateRuntimeFunction(FTy, FunctionName));
+ }
+ return Function;
+ }
+ operator llvm::Function *() {
+ return cast<llvm::Function>((llvm::Constant *)*this);
+ }
};
@@ -171,8 +166,9 @@ protected:
/// where the C code specifies const char*.
llvm::Constant *MakeConstantString(const std::string &Str,
const std::string &Name="") {
- llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
- return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros);
+ auto *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
/// Emits a linkonce_odr string, whose name is the prefix followed by the
/// string value. This allows the linker to combine the strings between
@@ -181,13 +177,14 @@ protected:
llvm::Constant *ExportUniqueString(const std::string &Str,
const std::string prefix) {
std::string name = prefix + Str;
- llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
+ auto *ConstStr = TheModule.getGlobalVariable(name);
if (!ConstStr) {
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
}
- return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros);
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
/// Generates a global structure, initialized by the elements in the vector.
/// The element types must match the types of the structure elements in the
@@ -237,8 +234,9 @@ protected:
NameAndAttributes += TypeStr;
NameAndAttributes += '\0';
NameAndAttributes += PD->getNameAsString();
- return llvm::ConstantExpr::getGetElementPtr(
- CGM.GetAddrOfConstantCString(NameAndAttributes), Zeros);
+ auto *ConstStr = CGM.GetAddrOfConstantCString(NameAndAttributes);
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
+ ConstStr, Zeros);
}
return MakeConstantString(PD->getNameAsString());
}
@@ -672,8 +670,8 @@ class CGObjCGNUstep : public CGObjCGNU {
slot->setMetadata(msgSendMDKind, node);
// Load the imp from the slot
- llvm::Value *imp =
- Builder.CreateLoad(Builder.CreateStructGEP(slot.getInstruction(), 4));
+ llvm::Value *imp = Builder.CreateLoad(
+ Builder.CreateStructGEP(nullptr, slot.getInstruction(), 4));
// The lookup function may have changed the receiver, so make sure we use
// the new one.
@@ -690,7 +688,7 @@ class CGObjCGNUstep : public CGObjCGNU {
CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
slot->setOnlyReadsMemory();
- return Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+ return Builder.CreateLoad(Builder.CreateStructGEP(nullptr, slot, 4));
}
public:
CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) {
@@ -1013,7 +1011,7 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
bool isWeak) {
- llvm::Value *ClassName = CGM.GetAddrOfConstantCString(Name);
+ llvm::GlobalVariable *ClassNameGV = CGM.GetAddrOfConstantCString(Name);
// With the incompatible ABI, this will need to be replaced with a direct
// reference to the class symbol. For the compatible nonfragile ABI we are
// still performing this lookup at run time but emitting the symbol for the
@@ -1023,7 +1021,8 @@ llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
// with memoized versions or with static references if it's safe to do so.
if (!isWeak)
EmitClassRef(Name);
- ClassName = CGF.Builder.CreateStructGEP(ClassName, 0);
+ llvm::Value *ClassName =
+ CGF.Builder.CreateStructGEP(ClassNameGV->getValueType(), ClassNameGV, 0);
llvm::Constant *ClassLookupFn =
CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, PtrToInt8Ty, true),
@@ -1056,9 +1055,9 @@ llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
}
if (!SelValue) {
SelValue = llvm::GlobalAlias::create(
- SelectorTy->getElementType(), 0, llvm::GlobalValue::PrivateLinkage,
+ SelectorTy, llvm::GlobalValue::PrivateLinkage,
".objc_selector_" + Sel.getAsString(), &TheModule);
- Types.push_back(TypedSelector(TypeEncoding, SelValue));
+ Types.emplace_back(TypeEncoding, SelValue);
}
if (lval) {
@@ -1143,21 +1142,22 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
// It's quite ugly hard-coding this. Ideally we'd generate it using the host
// platform's name mangling.
const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
- llvm::Constant *Vtable = TheModule.getGlobalVariable(vtableName);
+ auto *Vtable = TheModule.getGlobalVariable(vtableName);
if (!Vtable) {
Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true,
llvm::GlobalValue::ExternalLinkage,
nullptr, vtableName);
}
llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
- Vtable = llvm::ConstantExpr::getGetElementPtr(Vtable, Two);
- Vtable = llvm::ConstantExpr::getBitCast(Vtable, PtrToInt8Ty);
+ auto *BVtable = llvm::ConstantExpr::getBitCast(
+ llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two),
+ PtrToInt8Ty);
llvm::Constant *typeName =
ExportUniqueString(className, "__objc_eh_typename_");
std::vector<llvm::Constant*> fields;
- fields.push_back(Vtable);
+ fields.push_back(BVtable);
fields.push_back(typeName);
llvm::Constant *TI =
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
@@ -1261,25 +1261,25 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
if (IsClassMessage) {
if (!MetaClassPtrAlias) {
MetaClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ IdTy, llvm::GlobalValue::InternalLinkage,
".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = MetaClassPtrAlias;
} else {
if (!ClassPtrAlias) {
ClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ IdTy, llvm::GlobalValue::InternalLinkage,
".objc_class_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = ClassPtrAlias;
}
}
// Cast the pointer to a simplified version of the class structure
+ llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy, nullptr);
ReceiverClass = Builder.CreateBitCast(ReceiverClass,
- llvm::PointerType::getUnqual(
- llvm::StructType::get(IdTy, IdTy, nullptr)));
+ llvm::PointerType::getUnqual(CastTy));
// Get the superclass pointer
- ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1);
+ ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
// Load the superclass pointer
ReceiverClass = Builder.CreateLoad(ReceiverClass);
// Construct the structure used to look up the IMP
@@ -1287,8 +1287,10 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
Receiver->getType(), IdTy, nullptr);
llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
- Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
- Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
+ Builder.CreateStore(Receiver,
+ Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 0));
+ Builder.CreateStore(ReceiverClass,
+ Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 1));
ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
@@ -2119,9 +2121,8 @@ void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
// Get the class declaration for which the alias is specified.
ObjCInterfaceDecl *ClassDecl =
const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface());
- std::string ClassName = ClassDecl->getNameAsString();
- std::string AliasName = OAD->getNameAsString();
- ClassAliases.push_back(ClassAliasPair(ClassName,AliasName));
+ ClassAliases.emplace_back(ClassDecl->getNameAsString(),
+ OAD->getNameAsString());
}
void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
@@ -2294,7 +2295,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
// Get the correct ivar field
llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
- IvarList, offsetPointerIndexes);
+ cast<llvm::GlobalVariable>(IvarList)->getValueType(), IvarList,
+ offsetPointerIndexes);
// Get the existing variable, if one exists.
llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
if (offset) {
@@ -2366,7 +2368,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
std::vector<llvm::Constant*> Elements;
llvm::Constant *Statics = NULLPtr;
// Generate statics list:
- if (ConstantStrings.size()) {
+ if (!ConstantStrings.empty()) {
llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
ConstantStrings.size() + 1);
ConstantStrings.push_back(NULLPtr);
@@ -2439,8 +2441,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
// Number of static selectors
Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount));
- llvm::Constant *SelectorList = MakeGlobalArray(SelStructTy, Selectors,
- ".objc_selector_list");
+ llvm::GlobalVariable *SelectorList =
+ MakeGlobalArray(SelStructTy, Selectors, ".objc_selector_list");
Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
SelStructPtrTy));
@@ -2450,8 +2452,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
llvm::Constant *Idxs[] = {Zeros[0],
llvm::ConstantInt::get(Int32Ty, i), Zeros[0]};
// FIXME: We're generating redundant loads and stores here!
- llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(SelectorList,
- makeArrayRef(Idxs, 2));
+ llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(
+ SelectorList->getValueType(), SelectorList, makeArrayRef(Idxs, 2));
// If selectors are defined as an opaque type, cast the pointer to this
// type.
SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, SelectorTy);
@@ -2562,8 +2564,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
true);
if (TheClass) {
TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy);
- Builder.CreateCall2(RegisterAlias, TheClass,
- MakeConstantString(iter->second));
+ Builder.CreateCall(RegisterAlias,
+ {TheClass, MakeConstantString(iter->second)});
}
}
// Jump to end:
@@ -2679,7 +2681,7 @@ llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
llvm::Value *AddrWeakObj) {
CGBuilderTy &B = CGF.Builder;
AddrWeakObj = EnforceType(B, AddrWeakObj, PtrToIdTy);
- return B.CreateCall(WeakReadFn, AddrWeakObj);
+ return B.CreateCall(WeakReadFn.getType(), WeakReadFn, AddrWeakObj);
}
void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
@@ -2687,7 +2689,7 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- B.CreateCall2(WeakAssignFn, src, dst);
+ B.CreateCall(WeakAssignFn.getType(), WeakAssignFn, {src, dst});
}
void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
@@ -2696,11 +2698,9 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- if (!threadlocal)
- B.CreateCall2(GlobalAssignFn, src, dst);
- else
- // FIXME. Add threadloca assign API
- llvm_unreachable("EmitObjCGlobalAssign - Threal Local API NYI");
+ // FIXME. Add threadloca assign API
+ assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI");
+ B.CreateCall(GlobalAssignFn.getType(), GlobalAssignFn, {src, dst});
}
void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
@@ -2709,7 +2709,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, IdTy);
- B.CreateCall3(IvarAssignFn, src, dst, ivarOffset);
+ B.CreateCall(IvarAssignFn.getType(), IvarAssignFn, {src, dst, ivarOffset});
}
void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
@@ -2717,7 +2717,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- B.CreateCall2(StrongCastAssignFn, src, dst);
+ B.CreateCall(StrongCastAssignFn.getType(), StrongCastAssignFn, {src, dst});
}
void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
@@ -2728,7 +2728,7 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
DestPtr = EnforceType(B, DestPtr, PtrTy);
SrcPtr = EnforceType(B, SrcPtr, PtrTy);
- B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, Size);
+ B.CreateCall(MemMoveFn.getType(), MemMoveFn, {DestPtr, SrcPtr, Size});
}
llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index f91e8e1..a45446a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -486,7 +486,6 @@ public:
}
ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCCommonTypesHelper(){}
};
/// ObjCTypesHelper - Helper class that encapsulates lazy
@@ -595,7 +594,6 @@ public:
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCTypesHelper() {}
};
/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
@@ -733,7 +731,6 @@ public:
llvm::Type *EHTypePtrTy;
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCNonFragileABITypesHelper(){}
};
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
@@ -1678,14 +1675,13 @@ struct NullReturnState {
/// getConstantGEP() - Help routine to construct simple GEPs.
static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
- llvm::Constant *C,
- unsigned idx0,
+ llvm::GlobalVariable *C, unsigned idx0,
unsigned idx1) {
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
};
- return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
+ return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
}
/// hasObjCExceptionAttribute - Return true if this class or any super
@@ -1791,8 +1787,9 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+ CGF.Builder.CreateStore(
+ ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -1805,20 +1802,20 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
// the class's "isa" pointer. The following assumes that
// isa" is the first ivar in a class (which it must be).
Target = EmitClassRef(CGF, Class->getSuperClass());
- Target = CGF.Builder.CreateStructGEP(Target, 0);
+ Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
Target = CGF.Builder.CreateLoad(Target);
} else {
- llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
- llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
+ llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
+ llvm::Value *SuperPtr =
+ CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
Target = Super;
}
- }
- else if (isCategoryImpl)
+ } else if (isCategoryImpl)
Target = EmitClassRef(CGF, Class->getSuperClass());
else {
llvm::Value *ClassPtr = EmitSuperClassRef(Class);
- ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
+ ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
Target = CGF.Builder.CreateLoad(ClassPtr);
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext and
@@ -1826,8 +1823,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ CGF.Builder.CreateStore(
+ Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
return EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
ObjCSuper, ObjCTypes.SuperPtrCTy,
@@ -3810,15 +3807,16 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// Enter a try block:
// - Call objc_exception_try_enter to push ExceptionData on top of
// the EH stack.
- CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
+ CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
+ ExceptionData);
// - Call setjmp on the exception data buffer.
llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
- llvm::Value *SetJmpBuffer =
- CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
- llvm::CallInst *SetJmpResult =
- CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
+ llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
+ ObjCTypes.ExceptionDataTy, ExceptionData, GEPIndexes, "setjmp_buffer");
+ llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
+ ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
SetJmpResult->setCanReturnTwice();
// If setjmp returned 0, enter the protected block; otherwise,
@@ -5263,6 +5261,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
// const uint32_t size; // sizeof(struct _protocol_t)
// const uint32_t flags; // = 0
// const char ** extendedMethodTypes;
+ // const char *demangledName;
// }
// Holder for struct _protocol_list_t *
@@ -5275,6 +5274,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
+ Int8PtrTy,
nullptr);
// struct _protocol_t*
@@ -6207,6 +6207,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
/// const uint32_t size; // sizeof(struct _protocol_t)
/// const uint32_t flags; // = 0
/// const char ** extendedMethodTypes;
+/// const char *demangledName;
/// }
/// @endcode
///
@@ -6258,7 +6259,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
MethodTypesExt.insert(MethodTypesExt.end(),
OptMethodTypesExt.begin(), OptMethodTypesExt.end());
- llvm::Constant *Values[11];
+ llvm::Constant *Values[12];
// isa is NULL
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Values[1] = GetClassName(PD->getObjCRuntimeNameAsString());
@@ -6291,6 +6292,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
+ PD->getObjCRuntimeNameAsString(),
MethodTypesExt, ObjCTypes);
+ // const char *demangledName;
+ Values[11] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Values);
@@ -6562,7 +6566,8 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
args[1].RV = RValue::get(mref);
// Load the function to call from the message ref table.
- llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
+ llvm::Value *callee =
+ CGF.Builder.CreateStructGEP(ObjCTypes.MessageRefTy, mref, 0);
callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
@@ -6727,8 +6732,9 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+ CGF.Builder.CreateStore(
+ ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -6742,8 +6748,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ CGF.Builder.CreateStore(
+ Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
return (isVTableDispatchedSelector(Sel))
? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
@@ -6992,10 +6998,10 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
llvm::Constant *Values[] = {
- llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
- GetClassName(ID->getObjCRuntimeNameAsString()),
- GetClassGlobal(ClassName.str())
- };
+ llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(), VTableGV,
+ VTableIdx),
+ GetClassName(ID->getObjCRuntimeNameAsString()),
+ GetClassGlobal(ClassName.str())};
llvm::Constant *Init =
llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
index 3d013da..2ac6bb2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/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(),
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 22ee00f..8148839 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -13,6 +13,7 @@
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
+#include "CGCleanup.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
#include "llvm/ADT/ArrayRef.h"
@@ -27,61 +28,243 @@ using namespace clang;
using namespace CodeGen;
namespace {
-/// \brief API for captured statement code generation in OpenMP constructs.
+/// \brief Base class for handling code generation inside OpenMP regions.
class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
public:
- CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS,
- const VarDecl *ThreadIDVar)
- : CGCapturedStmtInfo(CS, CR_OpenMP), ThreadIDVar(ThreadIDVar),
- Directive(D) {
- assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
- }
+ /// \brief Kinds of OpenMP regions used in codegen.
+ enum CGOpenMPRegionKind {
+ /// \brief Region with outlined function for standalone 'parallel'
+ /// directive.
+ ParallelOutlinedRegion,
+ /// \brief Region with outlined function for standalone 'task' directive.
+ TaskOutlinedRegion,
+ /// \brief Region for constructs that do not require function outlining,
+ /// like 'for', 'sections', 'atomic' etc. directives.
+ InlinedRegion,
+ };
- /// \brief Gets a variable or parameter for storing global thread id
+ CGOpenMPRegionInfo(const CapturedStmt &CS,
+ const CGOpenMPRegionKind RegionKind,
+ const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
+ : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
+ CodeGen(CodeGen), Kind(Kind) {}
+
+ CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
+ const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
+ : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
+ Kind(Kind) {}
+
+ /// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
- const VarDecl *getThreadIDVariable() const { return ThreadIDVar; }
+ virtual const VarDecl *getThreadIDVariable() const = 0;
+
+ /// \brief Emit the captured statement body.
+ virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
+
+ /// \brief Get an LValue for the current ThreadID variable.
+ /// \return LValue for thread id variable. This LValue always has type int32*.
+ virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
- /// \brief Gets an LValue for the current ThreadID variable.
- LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
+ CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
+
+ OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
static bool classof(const CGCapturedStmtInfo *Info) {
return Info->getKind() == CR_OpenMP;
}
- /// \brief Emit the captured statement body.
- void EmitBody(CodeGenFunction &CGF, Stmt *S) override;
+protected:
+ CGOpenMPRegionKind RegionKind;
+ const RegionCodeGenTy &CodeGen;
+ OpenMPDirectiveKind Kind;
+};
+
+/// \brief API for captured statement code generation in OpenMP constructs.
+class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
+public:
+ CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
+ const RegionCodeGenTy &CodeGen,
+ OpenMPDirectiveKind Kind)
+ : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind),
+ ThreadIDVar(ThreadIDVar) {
+ assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
+ }
+ /// \brief Get a variable or parameter for storing global thread id
+ /// inside OpenMP construct.
+ const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
+
+ /// \brief Get the name of the capture helper.
+ StringRef getHelperName() const override { return ".omp_outlined."; }
+
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
+ ParallelOutlinedRegion;
+ }
+
+private:
+ /// \brief A variable or parameter storing global thread id for OpenMP
+ /// constructs.
+ const VarDecl *ThreadIDVar;
+};
+
+/// \brief API for captured statement code generation in OpenMP constructs.
+class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
+public:
+ CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
+ const VarDecl *ThreadIDVar,
+ const RegionCodeGenTy &CodeGen,
+ OpenMPDirectiveKind Kind)
+ : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind),
+ ThreadIDVar(ThreadIDVar) {
+ assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
+ }
+ /// \brief Get a variable or parameter for storing global thread id
+ /// inside OpenMP construct.
+ const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
+
+ /// \brief Get an LValue for the current ThreadID variable.
+ LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
/// \brief Get the name of the capture helper.
StringRef getHelperName() const override { return ".omp_outlined."; }
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
+ TaskOutlinedRegion;
+ }
+
private:
/// \brief A variable or parameter storing global thread id for OpenMP
/// constructs.
const VarDecl *ThreadIDVar;
- /// \brief OpenMP executable directive associated with the region.
- const OMPExecutableDirective &Directive;
};
+
+/// \brief API for inlined captured statement code generation in OpenMP
+/// constructs.
+class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
+public:
+ CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
+ const RegionCodeGenTy &CodeGen,
+ OpenMPDirectiveKind Kind)
+ : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI),
+ OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
+ // \brief Retrieve the value of the context parameter.
+ llvm::Value *getContextValue() const override {
+ if (OuterRegionInfo)
+ return OuterRegionInfo->getContextValue();
+ llvm_unreachable("No context value for inlined OpenMP region");
+ }
+ virtual void setContextValue(llvm::Value *V) override {
+ if (OuterRegionInfo) {
+ OuterRegionInfo->setContextValue(V);
+ return;
+ }
+ llvm_unreachable("No context value for inlined OpenMP region");
+ }
+ /// \brief Lookup the captured field decl for a variable.
+ const FieldDecl *lookup(const VarDecl *VD) const override {
+ if (OuterRegionInfo)
+ return OuterRegionInfo->lookup(VD);
+ // If there is no outer outlined region,no need to lookup in a list of
+ // captured variables, we can use the original one.
+ return nullptr;
+ }
+ FieldDecl *getThisFieldDecl() const override {
+ if (OuterRegionInfo)
+ return OuterRegionInfo->getThisFieldDecl();
+ return nullptr;
+ }
+ /// \brief Get a variable or parameter for storing global thread id
+ /// inside OpenMP construct.
+ const VarDecl *getThreadIDVariable() const override {
+ if (OuterRegionInfo)
+ return OuterRegionInfo->getThreadIDVariable();
+ return nullptr;
+ }
+
+ /// \brief Get the name of the capture helper.
+ StringRef getHelperName() const override {
+ if (auto *OuterRegionInfo = getOldCSI())
+ return OuterRegionInfo->getHelperName();
+ llvm_unreachable("No helper name for inlined OpenMP construct");
+ }
+
+ CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
+
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
+ }
+
+private:
+ /// \brief CodeGen info about outer OpenMP region.
+ CodeGenFunction::CGCapturedStmtInfo *OldCSI;
+ CGOpenMPRegionInfo *OuterRegionInfo;
+};
+
+/// \brief RAII for emitting code of OpenMP constructs.
+class InlinedOpenMPRegionRAII {
+ CodeGenFunction &CGF;
+
+public:
+ /// \brief Constructs region for combined constructs.
+ /// \param CodeGen Code generation sequence for combined directives. Includes
+ /// a list of functions used for code generation of implicitly inlined
+ /// regions.
+ InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
+ OpenMPDirectiveKind Kind)
+ : CGF(CGF) {
+ // Start emission for the construct.
+ CGF.CapturedStmtInfo =
+ new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind);
+ }
+ ~InlinedOpenMPRegionRAII() {
+ // Restore original CapturedStmtInfo only if we're done with code emission.
+ auto *OldCSI =
+ cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
+ delete CGF.CapturedStmtInfo;
+ CGF.CapturedStmtInfo = OldCSI;
+ }
+};
+
} // namespace
LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
return CGF.MakeNaturalAlignAddrLValue(
- CGF.GetAddrOfLocalVar(ThreadIDVar),
- CGF.getContext().getPointerType(ThreadIDVar->getType()));
+ CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(getThreadIDVariable()),
+ CGF.PointerAlignInBytes),
+ getThreadIDVariable()
+ ->getType()
+ ->castAs<PointerType>()
+ ->getPointeeType());
}
-void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) {
- CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
- CGF.EmitOMPPrivateClause(Directive, PrivateScope);
- CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
- if (PrivateScope.Privatize())
- // Emit implicit barrier to synchronize threads and avoid data races.
- CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(),
- /*IsExplicit=*/false);
- CGCapturedStmtInfo::EmitBody(CGF, S);
+void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CGF.EHStack.pushTerminate();
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CodeGen(CGF);
+ }
+ CGF.EHStack.popTerminate();
+}
+
+LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
+ CodeGenFunction &CGF) {
+ return CGF.MakeNaturalAlignAddrLValue(
+ CGF.GetAddrOfLocalVar(getThreadIDVariable()),
+ getThreadIDVariable()->getType());
}
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
- : CGM(CGM), DefaultOpenMPPSource(nullptr) {
+ : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
IdentTy = llvm::StructType::create(
"ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
@@ -93,18 +276,37 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
}
-llvm::Value *
-CGOpenMPRuntime::EmitOpenMPOutlinedFunction(const OMPExecutableDirective &D,
- const VarDecl *ThreadIDVar) {
+void CGOpenMPRuntime::clear() {
+ InternalVars.clear();
+}
+
+llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ assert(ThreadIDVar->getType()->isPointerType() &&
+ "thread id variable must be of type kmp_int32 *");
const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
- CGOpenMPRegionInfo CGInfo(D, *CS, ThreadIDVar);
- CGF.CapturedStmtInfo = &CGInfo;
+ CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
+ return CGF.GenerateCapturedStmtFunction(*CS);
+}
+
+llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ assert(!ThreadIDVar->getType()->isPointerType() &&
+ "thread id variable must be of type kmp_int32 for tasks");
+ auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
+ CodeGenFunction CGF(CGM, true);
+ CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
+ InnermostKind);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
return CGF.GenerateCapturedStmtFunction(*CS);
}
llvm::Value *
-CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
+CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
if (!Entry) {
if (!DefaultOpenMPPSource) {
@@ -134,12 +336,13 @@ CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
return Entry;
}
-llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
- CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) {
+llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPLocationFlags Flags) {
// If no debug info is generated - return global default location.
if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
Loc.isInvalid())
- return GetOrCreateDefaultOpenMPLocation(Flags);
+ return getOrCreateDefaultLocation(Flags);
assert(CGF.CurFn && "No function in current CodeGenFunction.");
@@ -159,14 +362,14 @@ llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
- CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags),
+ CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
llvm::ConstantExpr::getSizeOf(IdentTy),
CGM.PointerAlignInBytes);
}
// char **psource = &.kmpc_loc_<flags>.addr.psource;
- auto *PSource =
- CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
+ auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
+ IdentField_PSource);
auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
if (OMPDebugLoc == nullptr) {
@@ -189,8 +392,8 @@ llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
return LocValue;
}
-llvm::Value *CGOpenMPRuntime::GetOpenMPThreadID(CodeGenFunction &CGF,
- SourceLocation Loc) {
+llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
+ SourceLocation Loc) {
assert(CGF.CurFn && "No function in current CodeGenFunction.");
llvm::Value *ThreadID = nullptr;
@@ -204,36 +407,35 @@ llvm::Value *CGOpenMPRuntime::GetOpenMPThreadID(CodeGenFunction &CGF,
}
if (auto OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
- // Check if this an outlined function with thread id passed as argument.
- auto ThreadIDVar = OMPRegionInfo->getThreadIDVariable();
- auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
- auto RVal = CGF.EmitLoadOfLValue(LVal, Loc);
- LVal = CGF.MakeNaturalAlignAddrLValue(RVal.getScalarVal(),
- ThreadIDVar->getType());
- ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
- // If value loaded in entry block, cache it and use it everywhere in
- // function.
- if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
- auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
- Elem.second.ThreadID = ThreadID;
+ if (OMPRegionInfo->getThreadIDVariable()) {
+ // Check if this an outlined function with thread id passed as argument.
+ auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
+ ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
+ // If value loaded in entry block, cache it and use it everywhere in
+ // function.
+ if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ Elem.second.ThreadID = ThreadID;
+ }
+ return ThreadID;
}
- } else {
- // This is not an outlined function region - need to call __kmpc_int32
- // kmpc_global_thread_num(ident_t *loc).
- // Generate thread id value and cache this value for use across the
- // function.
- CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
- CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)};
- ThreadID = CGF.EmitRuntimeCall(
- CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
- auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
- Elem.second.ThreadID = ThreadID;
}
+
+ // This is not an outlined function region - need to call __kmpc_int32
+ // kmpc_global_thread_num(ident_t *loc).
+ // Generate thread id value and cache this value for use across the
+ // function.
+ CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
+ CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
+ ThreadID =
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
+ emitUpdateLocation(CGF, Loc));
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ Elem.second.ThreadID = ThreadID;
return ThreadID;
}
-void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) {
+void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
assert(CGF.CurFn && "No function in current CodeGenFunction.");
if (OpenMPLocThreadIDMap.count(CGF.CurFn))
OpenMPLocThreadIDMap.erase(CGF.CurFn);
@@ -248,7 +450,7 @@ llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
}
llvm::Constant *
-CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
+CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
llvm::Constant *RTLFn = nullptr;
switch (Function) {
case OMPRTL__kmpc_fork_call: {
@@ -334,85 +536,12 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
break;
}
- // Build __kmpc_for_static_init*(
- // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
- // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
- // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
- // kmp_int[32|64] incr, kmp_int[32|64] chunk);
- case OMPRTL__kmpc_for_static_init_4: {
- auto ITy = CGM.Int32Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
- llvm::Type *TypeParams[] = {
- getIdentTyPointerTy(), // loc
- CGM.Int32Ty, // tid
- CGM.Int32Ty, // schedtype
- llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
- PtrTy, // p_lower
- PtrTy, // p_upper
- PtrTy, // p_stride
- ITy, // incr
- ITy // chunk
- };
- llvm::FunctionType *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4");
- break;
- }
- case OMPRTL__kmpc_for_static_init_4u: {
- auto ITy = CGM.Int32Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
- llvm::Type *TypeParams[] = {
- getIdentTyPointerTy(), // loc
- CGM.Int32Ty, // tid
- CGM.Int32Ty, // schedtype
- llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
- PtrTy, // p_lower
- PtrTy, // p_upper
- PtrTy, // p_stride
- ITy, // incr
- ITy // chunk
- };
- llvm::FunctionType *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4u");
- break;
- }
- case OMPRTL__kmpc_for_static_init_8: {
- auto ITy = CGM.Int64Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
- llvm::Type *TypeParams[] = {
- getIdentTyPointerTy(), // loc
- CGM.Int32Ty, // tid
- CGM.Int32Ty, // schedtype
- llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
- PtrTy, // p_lower
- PtrTy, // p_upper
- PtrTy, // p_stride
- ITy, // incr
- ITy // chunk
- };
- llvm::FunctionType *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8");
- break;
- }
- case OMPRTL__kmpc_for_static_init_8u: {
- auto ITy = CGM.Int64Ty;
- auto PtrTy = llvm::PointerType::getUnqual(ITy);
- llvm::Type *TypeParams[] = {
- getIdentTyPointerTy(), // loc
- CGM.Int32Ty, // tid
- CGM.Int32Ty, // schedtype
- llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
- PtrTy, // p_lower
- PtrTy, // p_upper
- PtrTy, // p_stride
- ITy, // incr
- ITy // chunk
- };
+ case OMPRTL__kmpc_barrier: {
+ // 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);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8u");
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
break;
}
case OMPRTL__kmpc_for_static_fini: {
@@ -452,10 +581,10 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
break;
}
case OMPRTL__kmpc_flush: {
- // Build void __kmpc_flush(ident_t *loc, ...);
+ // Build void __kmpc_flush(ident_t *loc);
llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
llvm::FunctionType *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
break;
}
@@ -475,38 +604,365 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
break;
}
+ case OMPRTL__kmpc_omp_taskyield: {
+ // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
+ // int end_part);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
+ break;
+ }
+ case OMPRTL__kmpc_single: {
+ // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
+ break;
+ }
+ case OMPRTL__kmpc_end_single: {
+ // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
+ break;
+ }
+ case OMPRTL__kmpc_omp_task_alloc: {
+ // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
+ // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ // kmp_routine_entry_t *task_entry);
+ assert(KmpRoutineEntryPtrTy != nullptr &&
+ "Type kmp_routine_entry_t must be created.");
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
+ CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
+ // Return void * and then cast to particular kmp_task_t type.
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
+ break;
+ }
+ case OMPRTL__kmpc_omp_task: {
+ // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
+ // *new_task);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
+ break;
+ }
+ case OMPRTL__kmpc_copyprivate: {
+ // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
+ // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
+ // kmp_int32 didit);
+ llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
+ auto *CpyFnTy =
+ llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
+ CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
+ CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
+ break;
+ }
+ case OMPRTL__kmpc_reduce: {
+ // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
+ // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
+ llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
+ auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
+ CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
+ break;
+ }
+ case OMPRTL__kmpc_reduce_nowait: {
+ // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
+ // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
+ // *lck);
+ llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
+ auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
+ /*isVarArg=*/false);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
+ CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
+ break;
+ }
+ case OMPRTL__kmpc_end_reduce: {
+ // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
+ break;
+ }
+ case OMPRTL__kmpc_end_reduce_nowait: {
+ // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(KmpCriticalNameTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
+ break;
+ }
+ case OMPRTL__kmpc_omp_task_begin_if0: {
+ // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
+ // *new_task);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
+ break;
+ }
+ case OMPRTL__kmpc_omp_task_complete_if0: {
+ // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
+ // *new_task);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy,
+ /*Name=*/"__kmpc_omp_task_complete_if0");
+ break;
+ }
+ case OMPRTL__kmpc_ordered: {
+ // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
+ break;
+ }
+ case OMPRTL__kmpc_end_ordered: {
+ // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
+ break;
+ }
+ case OMPRTL__kmpc_omp_taskwait: {
+ // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
+ break;
+ }
+ case OMPRTL__kmpc_taskgroup: {
+ // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
+ break;
+ }
+ case OMPRTL__kmpc_end_taskgroup: {
+ // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
+ break;
+ }
+ case OMPRTL__kmpc_push_proc_bind: {
+ // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
+ // int proc_bind)
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
+ break;
+ }
+ case OMPRTL__kmpc_omp_task_with_deps: {
+ // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
+ // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
+ // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
+ CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
+ break;
+ }
+ case OMPRTL__kmpc_omp_wait_deps: {
+ // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
+ // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
+ // kmp_depend_info_t *noalias_dep_list);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ CGM.Int32Ty, CGM.VoidPtrTy,
+ CGM.Int32Ty, CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
+ break;
+ }
+ case OMPRTL__kmpc_cancellationpoint: {
+ // Build kmp_int32 __kmpc_cancellationpoint(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_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;
}
+llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
+ bool IVSigned) {
+ assert((IVSize == 32 || IVSize == 64) &&
+ "IV size is not compatible with the omp runtime");
+ auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
+ : "__kmpc_for_static_init_4u")
+ : (IVSigned ? "__kmpc_for_static_init_8"
+ : "__kmpc_for_static_init_8u");
+ auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ auto PtrTy = llvm::PointerType::getUnqual(ITy);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), // loc
+ CGM.Int32Ty, // tid
+ CGM.Int32Ty, // schedtype
+ llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
+ PtrTy, // p_lower
+ PtrTy, // p_upper
+ PtrTy, // p_stride
+ ITy, // incr
+ ITy // chunk
+ };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ return CGM.CreateRuntimeFunction(FnTy, Name);
+}
+
+llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
+ bool IVSigned) {
+ assert((IVSize == 32 || IVSize == 64) &&
+ "IV size is not compatible with the omp runtime");
+ auto Name =
+ IVSize == 32
+ ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
+ : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
+ auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
+ CGM.Int32Ty, // tid
+ CGM.Int32Ty, // schedtype
+ ITy, // lower
+ ITy, // upper
+ ITy, // stride
+ ITy // chunk
+ };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ return CGM.CreateRuntimeFunction(FnTy, Name);
+}
+
+llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
+ bool IVSigned) {
+ assert((IVSize == 32 || IVSize == 64) &&
+ "IV size is not compatible with the omp runtime");
+ auto Name =
+ IVSize == 32
+ ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
+ : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), // loc
+ CGM.Int32Ty, // tid
+ };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(FnTy, Name);
+}
+
+llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
+ bool IVSigned) {
+ assert((IVSize == 32 || IVSize == 64) &&
+ "IV size is not compatible with the omp runtime");
+ auto Name =
+ IVSize == 32
+ ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
+ : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
+ auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
+ auto PtrTy = llvm::PointerType::getUnqual(ITy);
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), // loc
+ CGM.Int32Ty, // tid
+ llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
+ PtrTy, // p_lower
+ PtrTy, // p_upper
+ PtrTy // p_stride
+ };
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ return CGM.CreateRuntimeFunction(FnTy, Name);
+}
+
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,
+ return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Twine(CGM.getMangledName(VD)) + ".cache.");
}
-llvm::Value *CGOpenMPRuntime::getOMPAddrOfThreadPrivate(CodeGenFunction &CGF,
- const VarDecl *VD,
- llvm::Value *VDAddr,
- SourceLocation Loc) {
+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[] = {EmitOpenMPUpdateLocation(CGF, Loc),
- GetOpenMPThreadID(CGF, Loc),
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
getOrCreateThreadPrivateCache(VD)};
return CGF.EmitRuntimeCall(
- CreateRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
+ createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
}
-void CGOpenMPRuntime::EmitOMPThreadPrivateVarInit(
+void CGOpenMPRuntime::emitThreadPrivateVarInit(
CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
// Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
// library.
- auto OMPLoc = EmitOpenMPUpdateLocation(CGF, Loc);
- CGF.EmitRuntimeCall(CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num),
+ auto OMPLoc = emitUpdateLocation(CGF, Loc);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
OMPLoc);
// Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
// to register constructor/destructor for variable.
@@ -514,12 +970,16 @@ void CGOpenMPRuntime::EmitOMPThreadPrivateVarInit(
CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
Ctor, CopyCtor, Dtor};
CGF.EmitRuntimeCall(
- CreateRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
+ createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
}
-llvm::Function *CGOpenMPRuntime::EmitOMPThreadPrivateVarDefinition(
+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);
@@ -620,54 +1080,121 @@ llvm::Function *CGOpenMPRuntime::EmitOMPThreadPrivateVarDefinition(
InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
CGM.getTypes().arrangeNullaryFunction(), ArgList,
Loc);
- EmitOMPThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
+ emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
InitCGF.FinishFunction();
return InitFunction;
}
- EmitOMPThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
+ emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
}
return nullptr;
}
-void CGOpenMPRuntime::EmitOMPParallelCall(CodeGenFunction &CGF,
- SourceLocation Loc,
- llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct) {
- // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
- llvm::Value *Args[] = {
- EmitOpenMPUpdateLocation(CGF, Loc),
- CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
- // (there is only one additional argument - 'context')
- CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
- CGF.EmitCastToVoidPtr(CapturedStruct)};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_fork_call);
- CGF.EmitRuntimeCall(RTLFn, Args);
-}
-
-void CGOpenMPRuntime::EmitOMPSerialCall(CodeGenFunction &CGF,
- SourceLocation Loc,
- llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct) {
- auto ThreadID = GetOpenMPThreadID(CGF, Loc);
- // Build calls:
- // __kmpc_serialized_parallel(&Loc, GTid);
- llvm::Value *SerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_serialized_parallel);
- CGF.EmitRuntimeCall(RTLFn, SerArgs);
-
- // OutlinedFn(&GTid, &zero, CapturedStruct);
- auto ThreadIDAddr = EmitThreadIDAddress(CGF, Loc);
- auto Int32Ty =
- CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
- auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
- CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
+/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
+/// function. Here is the logic:
+/// if (Cond) {
+/// ThenGen();
+/// } else {
+/// ElseGen();
+/// }
+static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
+ const RegionCodeGenTy &ThenGen,
+ const RegionCodeGenTy &ElseGen) {
+ CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
+
+ // If the condition constant folds and can be elided, try to avoid emitting
+ // the condition and the dead arm of the if/else.
+ bool CondConstant;
+ if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ if (CondConstant) {
+ ThenGen(CGF);
+ } else {
+ ElseGen(CGF);
+ }
+ return;
+ }
+
+ // Otherwise, the condition did not fold, or we couldn't elide it. Just
+ // emit the conditional branch.
+ auto ThenBlock = CGF.createBasicBlock("omp_if.then");
+ auto ElseBlock = CGF.createBasicBlock("omp_if.else");
+ auto ContBlock = CGF.createBasicBlock("omp_if.end");
+ CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
+
+ // Emit the 'then' code.
+ CGF.EmitBlock(ThenBlock);
+ {
+ CodeGenFunction::RunCleanupsScope ThenScope(CGF);
+ ThenGen(CGF);
+ }
+ CGF.EmitBranch(ContBlock);
+ // Emit the 'else' code if present.
+ {
+ // There is no need to emit line number for unconditional branch.
+ auto NL = ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(ElseBlock);
+ }
+ {
+ CodeGenFunction::RunCleanupsScope ThenScope(CGF);
+ ElseGen(CGF);
+ }
+ {
+ // There is no need to emit line number for unconditional branch.
+ auto NL = ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBranch(ContBlock);
+ }
+ // Emit the continuation block for code after the if.
+ CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
+}
- // __kmpc_end_serialized_parallel(&Loc, GTid);
- llvm::Value *EndSerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID};
- RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel);
- CGF.EmitRuntimeCall(RTLFn, EndSerArgs);
+void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ llvm::Value *CapturedStruct,
+ const Expr *IfCond) {
+ auto *RTLoc = emitUpdateLocation(CGF, Loc);
+ auto &&ThenGen =
+ [this, OutlinedFn, CapturedStruct, RTLoc](CodeGenFunction &CGF) {
+ // Build call __kmpc_fork_call(loc, 1, microtask,
+ // captured_struct/*context*/)
+ llvm::Value *Args[] = {
+ RTLoc,
+ CGF.Builder.getInt32(
+ 1), // Number of arguments after 'microtask' argument
+ // (there is only one additional argument - 'context')
+ CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
+ CGF.EmitCastToVoidPtr(CapturedStruct)};
+ auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
+ CGF.EmitRuntimeCall(RTLFn, Args);
+ };
+ auto &&ElseGen = [this, OutlinedFn, CapturedStruct, RTLoc, Loc](
+ CodeGenFunction &CGF) {
+ auto ThreadID = getThreadID(CGF, Loc);
+ // Build calls:
+ // __kmpc_serialized_parallel(&Loc, GTid);
+ llvm::Value *Args[] = {RTLoc, ThreadID};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
+ Args);
+
+ // OutlinedFn(&GTid, &zero, CapturedStruct);
+ auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
+ auto Int32Ty = CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32,
+ /*Signed*/ true);
+ auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
+ llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
+ CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
+
+ // __kmpc_end_serialized_parallel(&Loc, GTid);
+ llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
+ CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
+ };
+ if (IfCond) {
+ emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
+ } else {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ ThenGen(CGF);
+ }
}
// If we're inside an (outlined) parallel region, use the region info's
@@ -676,13 +1203,14 @@ void CGOpenMPRuntime::EmitOMPSerialCall(CodeGenFunction &CGF,
// regular serial code region, get thread ID by calling kmp_int32
// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
// return the address of that temp.
-llvm::Value *CGOpenMPRuntime::EmitThreadIDAddress(CodeGenFunction &CGF,
+llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
SourceLocation Loc) {
if (auto OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
- return CGF.EmitLoadOfLValue(OMPRegionInfo->getThreadIDVariableLValue(CGF),
- SourceLocation()).getScalarVal();
- auto ThreadID = GetOpenMPThreadID(CGF, Loc);
+ if (OMPRegionInfo->getThreadIDVariable())
+ return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
+
+ auto ThreadID = getThreadID(CGF, Loc);
auto Int32Ty =
CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
@@ -693,7 +1221,7 @@ llvm::Value *CGOpenMPRuntime::EmitThreadIDAddress(CodeGenFunction &CGF,
}
llvm::Constant *
-CGOpenMPRuntime::GetOrCreateInternalVariable(llvm::Type *Ty,
+CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
const llvm::Twine &Name) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
@@ -712,31 +1240,52 @@ CGOpenMPRuntime::GetOrCreateInternalVariable(llvm::Type *Ty,
Elem.first());
}
-llvm::Value *CGOpenMPRuntime::GetCriticalRegionLock(StringRef CriticalName) {
+llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
llvm::Twine Name(".gomp_critical_user_", CriticalName);
- return GetOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
+ return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
}
-void CGOpenMPRuntime::EmitOMPCriticalRegion(
- CodeGenFunction &CGF, StringRef CriticalName,
- const std::function<void()> &CriticalOpGen, SourceLocation Loc) {
- auto RegionLock = GetCriticalRegionLock(CriticalName);
+namespace {
+template <size_t N> class CallEndCleanup : public EHScopeStack::Cleanup {
+ llvm::Value *Callee;
+ llvm::Value *Args[N];
+
+public:
+ CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
+ : Callee(Callee) {
+ assert(CleanupArgs.size() == N);
+ std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
+ }
+ void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
+ CGF.EmitRuntimeCall(Callee, Args);
+ }
+};
+} // namespace
+
+void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
+ StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen,
+ SourceLocation Loc) {
// __kmpc_critical(ident_t *, gtid, Lock);
// CriticalOpGen();
// __kmpc_end_critical(ident_t *, gtid, Lock);
// Prepare arguments and build a call to __kmpc_critical
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
- GetOpenMPThreadID(CGF, Loc), RegionLock};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_critical);
- CGF.EmitRuntimeCall(RTLFn, Args);
- CriticalOpGen();
- // Build a call to __kmpc_end_critical
- RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_end_critical);
- CGF.EmitRuntimeCall(RTLFn, Args);
-}
-
-static void EmitOMPIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
- const std::function<void()> &BodyOpGen) {
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ getCriticalRegionLock(CriticalName)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
+ // Build a call to __kmpc_end_critical
+ CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
+ llvm::makeArrayRef(Args));
+ emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
+ }
+}
+
+static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
+ OpenMPDirectiveKind Kind,
+ const RegionCodeGenTy &BodyOpGen) {
llvm::Value *CallBool = CGF.EmitScalarConversion(
IfCond,
CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
@@ -747,61 +1296,274 @@ static void EmitOMPIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
// Generate the branch (If-stmt)
CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
CGF.EmitBlock(ThenBlock);
- BodyOpGen();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
// Emit the rest of bblocks/branches
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock, true);
}
-void CGOpenMPRuntime::EmitOMPMasterRegion(
- CodeGenFunction &CGF, const std::function<void()> &MasterOpGen,
- SourceLocation Loc) {
+void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc) {
// if(__kmpc_master(ident_t *, gtid)) {
// MasterOpGen();
// __kmpc_end_master(ident_t *, gtid);
// }
// Prepare arguments and build a call to __kmpc_master
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
- GetOpenMPThreadID(CGF, Loc)};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_master);
- auto *IsMaster = CGF.EmitRuntimeCall(RTLFn, Args);
- EmitOMPIfStmt(CGF, IsMaster, [&]() -> void {
- MasterOpGen();
- // Build a call to __kmpc_end_master.
- // OpenMP [1.2.2 OpenMP Language Terminology]
- // For C/C++, an executable statement, possibly compound, with a single
- // entry at the top and a single exit at the bottom, or an OpenMP construct.
- // * Access to the structured block must not be the result of a branch.
- // * The point of exit cannot be a branch out of the structured block.
- // * The point of entry must not be a call to setjmp().
- // * longjmp() and throw() must not violate the entry/exit criteria.
- // * An expression statement, iteration statement, selection statement, or
- // try block is considered to be a structured block if the corresponding
- // compound statement obtained by enclosing it in { and } would be a
- // structured block.
- // It is analyzed in Sema, so we can just call __kmpc_end_master() on
- // fallthrough rather than pushing a normal cleanup for it.
- RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_end_master);
- CGF.EmitRuntimeCall(RTLFn, Args);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ auto *IsMaster =
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
+ typedef CallEndCleanup<std::extent<decltype(Args)>::value>
+ MasterCallEndCleanup;
+ emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
+ llvm::makeArrayRef(Args));
+ MasterOpGen(CGF);
});
}
-void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF,
- SourceLocation Loc, bool IsExplicit) {
- // Build call __kmpc_cancel_barrier(loc, thread_id);
- auto Flags = static_cast<OpenMPLocationFlags>(
- OMP_IDENT_KMPC |
- (IsExplicit ? OMP_IDENT_BARRIER_EXPL : OMP_IDENT_BARRIER_IMPL));
+void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
+}
+
+void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &TaskgroupOpGen,
+ SourceLocation Loc) {
+ // __kmpc_taskgroup(ident_t *, gtid);
+ // TaskgroupOpGen();
+ // __kmpc_end_taskgroup(ident_t *, gtid);
+ // Prepare arguments and build a call to __kmpc_taskgroup
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
+ // Build a call to __kmpc_end_taskgroup
+ CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
+ llvm::makeArrayRef(Args));
+ emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
+ }
+}
+
+static llvm::Value *emitCopyprivateCopyFunction(
+ CodeGenModule &CGM, llvm::Type *ArgsType,
+ ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
+ ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
+ auto &C = CGM.getContext();
+ // void copy_func(void *LHSArg, void *RHSArg);
+ FunctionArgList Args;
+ ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ Args.push_back(&LHSArg);
+ Args.push_back(&RHSArg);
+ FunctionType::ExtInfo EI;
+ auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, Args, EI, /*isVariadic=*/false);
+ auto *Fn = llvm::Function::Create(
+ CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
+ ".omp.copyprivate.copy_func", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
+ CodeGenFunction CGF(CGM);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+ // Dest = (void*[n])(LHSArg);
+ // Src = (void*[n])(RHSArg);
+ auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+ auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+ // *(Type0*)Dst[0] = *(Type0*)Src[0];
+ // *(Type1*)Dst[1] = *(Type1*)Src[1];
+ // ...
+ // *(Typen*)Dst[n] = *(Typen*)Src[n];
+ for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
+ auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(nullptr, LHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
+ auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(nullptr, RHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
+ auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
+ QualType Type = VD->getType();
+ CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr,
+ cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
+ AssignmentOps[I]);
+ }
+ CGF.FinishFunction();
+ return Fn;
+}
+
+void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &SingleOpGen,
+ SourceLocation Loc,
+ ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> DstExprs,
+ ArrayRef<const Expr *> AssignmentOps) {
+ assert(CopyprivateVars.size() == SrcExprs.size() &&
+ CopyprivateVars.size() == DstExprs.size() &&
+ CopyprivateVars.size() == AssignmentOps.size());
+ auto &C = CGM.getContext();
+ // int32 did_it = 0;
+ // if(__kmpc_single(ident_t *, gtid)) {
+ // SingleOpGen();
+ // __kmpc_end_single(ident_t *, gtid);
+ // did_it = 1;
+ // }
+ // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
+ // <copy_func>, did_it);
+
+ llvm::AllocaInst *DidIt = nullptr;
+ if (!CopyprivateVars.empty()) {
+ // int32 did_it = 0;
+ auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
+ CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(0), DidIt,
+ DidIt->getAlignment());
+ }
+ // Prepare arguments and build a call to __kmpc_single
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ auto *IsSingle =
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
+ typedef CallEndCleanup<std::extent<decltype(Args)>::value>
+ SingleCallEndCleanup;
+ emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
+ llvm::makeArrayRef(Args));
+ SingleOpGen(CGF);
+ if (DidIt) {
+ // did_it = 1;
+ CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
+ DidIt->getAlignment());
+ }
+ });
+ // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
+ // <copy_func>, did_it);
+ if (DidIt) {
+ llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
+ auto CopyprivateArrayTy =
+ C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ // Create a list of all private variables for copyprivate.
+ auto *CopyprivateList =
+ CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
+ for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
+ auto *Elem = CGF.Builder.CreateStructGEP(
+ CopyprivateList->getAllocatedType(), CopyprivateList, I);
+ CGF.Builder.CreateAlignedStore(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
+ Elem, CGM.PointerAlignInBytes);
+ }
+ // Build function that copies private values from single region to all other
+ // threads in the corresponding parallel region.
+ auto *CpyFn = emitCopyprivateCopyFunction(
+ CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
+ CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
+ auto *BufSize = llvm::ConstantInt::get(
+ CGM.SizeTy, C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
+ auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
+ CGF.VoidPtrTy);
+ auto *DidItVal =
+ CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes);
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc), // ident_t *<loc>
+ getThreadID(CGF, Loc), // i32 <gtid>
+ BufSize, // size_t <buf_size>
+ CL, // void *<copyprivate list>
+ CpyFn, // void (*) (void *, void *) <copy_func>
+ DidItVal // i32 did_it
+ };
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
+ }
+}
+
+void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &OrderedOpGen,
+ SourceLocation Loc) {
+ // __kmpc_ordered(ident_t *, gtid);
+ // OrderedOpGen();
+ // __kmpc_end_ordered(ident_t *, gtid);
+ // Prepare arguments and build a call to __kmpc_ordered
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
+ // Build a call to __kmpc_end_ordered
+ CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
+ llvm::makeArrayRef(Args));
+ emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
+ }
+}
+
+void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind,
+ bool CheckForCancel) {
// Build call __kmpc_cancel_barrier(loc, thread_id);
- // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this
- // one provides the same functionality and adds initial support for
- // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier()
- // is provided default by the runtime library so it safe to make such
- // replacement.
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, Flags),
- GetOpenMPThreadID(CGF, Loc)};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_cancel_barrier);
- CGF.EmitRuntimeCall(RTLFn, Args);
+ // Build call __kmpc_barrier(loc, thread_id);
+ OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
+ if (Kind == OMPD_for) {
+ Flags =
+ static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
+ } else if (Kind == OMPD_sections) {
+ Flags = static_cast<OpenMPLocationFlags>(Flags |
+ OMP_IDENT_BARRIER_IMPL_SECTIONS);
+ } else if (Kind == OMPD_single) {
+ Flags =
+ static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
+ } else if (Kind == OMPD_barrier) {
+ Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
+ } else {
+ Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
+ }
+ // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
+ // thread_id);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
+ getThreadID(CGF, Loc)};
+ if (auto *OMPRegionInfo =
+ dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
+ auto CancelDestination =
+ CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
+ if (CancelDestination.isValid()) {
+ auto *Result = CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
+ if (CheckForCancel) {
+ // if (__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);
+ // exit from construct;
+ CGF.EmitBranchThroughCleanup(CancelDestination);
+ CGF.EmitBlock(ContBB, /*IsFinished=*/true);
+ }
+ return;
+ }
+ }
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
}
/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
@@ -817,106 +1579,1258 @@ enum OpenMPSchedType {
OMP_sch_auto = 38,
/// \brief Lower bound for 'ordered' versions.
OMP_ord_lower = 64,
- /// \brief Lower bound for 'nomerge' versions.
- OMP_nm_lower = 160,
+ OMP_ord_static_chunked = 65,
+ OMP_ord_static = 66,
+ OMP_ord_dynamic_chunked = 67,
+ OMP_ord_guided_chunked = 68,
+ OMP_ord_runtime = 69,
+ OMP_ord_auto = 70,
+ OMP_sch_default = OMP_sch_static,
};
/// \brief Map the OpenMP loop schedule to the runtime enumeration.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
- bool Chunked) {
+ bool Chunked, bool Ordered) {
switch (ScheduleKind) {
case OMPC_SCHEDULE_static:
- return Chunked ? OMP_sch_static_chunked : OMP_sch_static;
+ return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
+ : (Ordered ? OMP_ord_static : OMP_sch_static);
case OMPC_SCHEDULE_dynamic:
- return OMP_sch_dynamic_chunked;
+ return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
case OMPC_SCHEDULE_guided:
- return OMP_sch_guided_chunked;
- case OMPC_SCHEDULE_auto:
- return OMP_sch_auto;
+ return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
case OMPC_SCHEDULE_runtime:
- return OMP_sch_runtime;
+ return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
+ case OMPC_SCHEDULE_auto:
+ return Ordered ? OMP_ord_auto : OMP_sch_auto;
case OMPC_SCHEDULE_unknown:
assert(!Chunked && "chunk was specified but schedule kind not known");
- return OMP_sch_static;
+ return Ordered ? OMP_ord_static : OMP_sch_static;
}
llvm_unreachable("Unexpected runtime schedule");
}
bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked) const {
- auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
+ auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
return Schedule == OMP_sch_static;
}
-void CGOpenMPRuntime::EmitOMPForInit(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind ScheduleKind,
- unsigned IVSize, bool IVSigned,
- llvm::Value *IL, llvm::Value *LB,
- llvm::Value *UB, llvm::Value *ST,
- llvm::Value *Chunk) {
- OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunk != nullptr);
- // Call __kmpc_for_static_init(
- // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
- // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
- // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
- // kmp_int[32|64] incr, kmp_int[32|64] chunk);
- // TODO: Implement dynamic schedule.
-
- // If the Chunk was not specified in the clause - use default value 1.
- if (Chunk == nullptr)
- Chunk = CGF.Builder.getIntN(IVSize, /*C*/ 1);
+bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
+ auto Schedule =
+ getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
+ assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
+ return Schedule != OMP_sch_static;
+}
+
+void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPScheduleClauseKind ScheduleKind,
+ unsigned IVSize, bool IVSigned, bool Ordered,
+ llvm::Value *IL, llvm::Value *LB,
+ llvm::Value *UB, llvm::Value *ST,
+ llvm::Value *Chunk) {
+ OpenMPSchedType Schedule =
+ getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
+ if (Ordered ||
+ (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
+ Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)) {
+ // Call __kmpc_dispatch_init(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
+ // kmp_int[32|64] lower, kmp_int[32|64] upper,
+ // kmp_int[32|64] stride, kmp_int[32|64] chunk);
+ // If the Chunk was not specified in the clause - use default value 1.
+ if (Chunk == nullptr)
+ Chunk = CGF.Builder.getIntN(IVSize, 1);
+ llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(Schedule), // Schedule type
+ CGF.Builder.getIntN(IVSize, 0), // Lower
+ UB, // Upper
+ CGF.Builder.getIntN(IVSize, 1), // Stride
+ Chunk // Chunk
+ };
+ CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
+ } else {
+ // Call __kmpc_for_static_init(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
+ // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
+ // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
+ // kmp_int[32|64] incr, kmp_int[32|64] chunk);
+ if (Chunk == nullptr) {
+ assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
+ "expected static non-chunked schedule");
+ // If the Chunk was not specified in the clause - use default value 1.
+ Chunk = CGF.Builder.getIntN(IVSize, 1);
+ } else
+ assert((Schedule == OMP_sch_static_chunked ||
+ Schedule == OMP_ord_static_chunked) &&
+ "expected static chunked schedule");
+ llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(Schedule), // Schedule type
+ IL, // &isLastIter
+ LB, // &LB
+ UB, // &UB
+ ST, // &Stride
+ CGF.Builder.getIntN(IVSize, 1), // Incr
+ Chunk // Chunk
+ };
+ CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
+ }
+}
+
+void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
+ Args);
+}
+
+void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ unsigned IVSize,
+ bool IVSigned) {
+ // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc)};
+ CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
+}
+
+llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
+ SourceLocation Loc, unsigned IVSize,
+ bool IVSigned, llvm::Value *IL,
+ llvm::Value *LB, llvm::Value *UB,
+ llvm::Value *ST) {
+ // Call __kmpc_dispatch_next(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
+ // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
+ // kmp_int[32|64] *p_stride);
llvm::Value *Args[] = {
- EmitOpenMPUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
- GetOpenMPThreadID(CGF, Loc),
- CGF.Builder.getInt32(Schedule), // Schedule type
- IL, // &isLastIter
- LB, // &LB
- UB, // &UB
- ST, // &Stride
- CGF.Builder.getIntN(IVSize, 1), // Incr
- Chunk // Chunk
+ emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
+ IL, // &isLastIter
+ LB, // &Lower
+ UB, // &Upper
+ ST // &Stride
};
- assert((IVSize == 32 || IVSize == 64) &&
- "Index size is not compatible with the omp runtime");
- auto F = IVSize == 32 ? (IVSigned ? OMPRTL__kmpc_for_static_init_4
- : OMPRTL__kmpc_for_static_init_4u)
- : (IVSigned ? OMPRTL__kmpc_for_static_init_8
- : OMPRTL__kmpc_for_static_init_8u);
- auto RTLFn = CreateRuntimeFunction(F);
- CGF.EmitRuntimeCall(RTLFn, Args);
-}
-
-void CGOpenMPRuntime::EmitOMPForFinish(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind ScheduleKind) {
- assert((ScheduleKind == OMPC_SCHEDULE_static ||
- ScheduleKind == OMPC_SCHEDULE_unknown) &&
- "Non-static schedule kinds are not yet implemented");
- // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
- GetOpenMPThreadID(CGF, Loc)};
- auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_for_static_fini);
- CGF.EmitRuntimeCall(RTLFn, Args);
+ llvm::Value *Call =
+ CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
+ return CGF.EmitScalarConversion(
+ Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
+ CGF.getContext().BoolTy);
}
-void CGOpenMPRuntime::EmitOMPNumThreadsClause(CodeGenFunction &CGF,
- llvm::Value *NumThreads,
- SourceLocation Loc) {
+void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
+ llvm::Value *NumThreads,
+ SourceLocation Loc) {
// Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
llvm::Value *Args[] = {
- EmitOpenMPUpdateLocation(CGF, Loc), GetOpenMPThreadID(CGF, Loc),
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
- llvm::Constant *RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_push_num_threads);
- CGF.EmitRuntimeCall(RTLFn, Args);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
+ Args);
+}
+
+void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
+ OpenMPProcBindClauseKind ProcBind,
+ SourceLocation Loc) {
+ // Constants for proc bind value accepted by the runtime.
+ enum ProcBindTy {
+ ProcBindFalse = 0,
+ ProcBindTrue,
+ ProcBindMaster,
+ ProcBindClose,
+ ProcBindSpread,
+ ProcBindIntel,
+ ProcBindDefault
+ } RuntimeProcBind;
+ switch (ProcBind) {
+ case OMPC_PROC_BIND_master:
+ RuntimeProcBind = ProcBindMaster;
+ break;
+ case OMPC_PROC_BIND_close:
+ RuntimeProcBind = ProcBindClose;
+ break;
+ case OMPC_PROC_BIND_spread:
+ RuntimeProcBind = ProcBindSpread;
+ break;
+ case OMPC_PROC_BIND_unknown:
+ llvm_unreachable("Unsupported proc_bind value.");
+ }
+ // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
+}
+
+void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
+ SourceLocation Loc) {
+ // Build call void __kmpc_flush(ident_t *loc)
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
+ emitUpdateLocation(CGF, Loc));
+}
+
+namespace {
+/// \brief Indexes of fields for type kmp_task_t.
+enum KmpTaskTFields {
+ /// \brief List of shared variables.
+ KmpTaskTShareds,
+ /// \brief Task routine.
+ KmpTaskTRoutine,
+ /// \brief Partition id for the untied tasks.
+ KmpTaskTPartId,
+ /// \brief Function with call of destructors for private variables.
+ KmpTaskTDestructors,
+};
+} // namespace
+
+void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
+ if (!KmpRoutineEntryPtrTy) {
+ // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
+ auto &C = CGM.getContext();
+ QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ KmpRoutineEntryPtrQTy = C.getPointerType(
+ C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
+ KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
+ }
+}
+
+static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
+ QualType FieldTy) {
+ auto *Field = FieldDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
+ C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ DC->addDecl(Field);
+}
+
+namespace {
+struct PrivateHelpersTy {
+ PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
+ const VarDecl *PrivateElemInit)
+ : Original(Original), PrivateCopy(PrivateCopy),
+ PrivateElemInit(PrivateElemInit) {}
+ const VarDecl *Original;
+ const VarDecl *PrivateCopy;
+ const VarDecl *PrivateElemInit;
+};
+typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
+} // namespace
+
+static RecordDecl *
+createPrivatesRecordDecl(CodeGenModule &CGM,
+ const ArrayRef<PrivateDataTy> Privates) {
+ if (!Privates.empty()) {
+ auto &C = CGM.getContext();
+ // Build struct .kmp_privates_t. {
+ // /* private vars */
+ // };
+ auto *RD = C.buildImplicitRecord(".kmp_privates.t");
+ RD->startDefinition();
+ for (auto &&Pair : Privates) {
+ auto Type = Pair.second.Original->getType();
+ Type = Type.getNonReferenceType();
+ addFieldToRecordDecl(C, RD, Type);
+ }
+ RD->completeDefinition();
+ return RD;
+ }
+ return nullptr;
+}
+
+static RecordDecl *
+createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
+ QualType KmpRoutineEntryPointerQTy) {
+ auto &C = CGM.getContext();
+ // Build struct kmp_task_t {
+ // void * shareds;
+ // kmp_routine_entry_t routine;
+ // kmp_int32 part_id;
+ // kmp_routine_entry_t destructors;
+ // };
+ auto *RD = C.buildImplicitRecord("kmp_task_t");
+ RD->startDefinition();
+ addFieldToRecordDecl(C, RD, C.VoidPtrTy);
+ addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
+ addFieldToRecordDecl(C, RD, KmpInt32Ty);
+ addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
+ RD->completeDefinition();
+ return RD;
+}
+
+static RecordDecl *
+createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
+ const ArrayRef<PrivateDataTy> Privates) {
+ auto &C = CGM.getContext();
+ // Build struct kmp_task_t_with_privates {
+ // kmp_task_t task_data;
+ // .kmp_privates_t. privates;
+ // };
+ auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
+ RD->startDefinition();
+ addFieldToRecordDecl(C, RD, KmpTaskTQTy);
+ if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
+ addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
+ }
+ RD->completeDefinition();
+ return RD;
+}
+
+/// \brief Emit a proxy function which accepts kmp_task_t as the second
+/// argument.
+/// \code
+/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
+/// tt->shareds);
+/// return 0;
+/// }
+/// \endcode
+static llvm::Value *
+emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
+ QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
+ QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
+ QualType SharedsPtrTy, llvm::Value *TaskFunction,
+ llvm::Value *TaskPrivatesMap) {
+ auto &C = CGM.getContext();
+ FunctionArgList Args;
+ ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
+ ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ Args.push_back(&GtidArg);
+ Args.push_back(&TaskTypeArg);
+ FunctionType::ExtInfo Info;
+ auto &TaskEntryFnInfo =
+ CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
+ /*isVariadic=*/false);
+ auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
+ auto *TaskEntry =
+ llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
+ ".omp_task_entry.", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
+ CodeGenFunction CGF(CGM);
+ CGF.disableDebugInfo();
+ CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
+
+ // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
+ // tt->task_data.shareds);
+ auto *GtidParam = CGF.EmitLoadOfScalar(
+ CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
+ C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
+ auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
+ LValue TDBase =
+ CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
+ auto *KmpTaskTWithPrivatesQTyRD =
+ cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
+ LValue Base =
+ CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
+ auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
+ auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
+ auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
+ auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
+
+ auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
+ auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
+ auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
+ CGF.ConvertTypeForMem(SharedsPtrTy));
+
+ auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
+ llvm::Value *PrivatesParam;
+ if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
+ auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
+ PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PrivatesLVal.getAddress(), CGF.VoidPtrTy);
+ } else {
+ PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
+ }
+
+ llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
+ TaskPrivatesMap, SharedsParam};
+ CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
+ CGF.EmitStoreThroughLValue(
+ RValue::get(CGF.Builder.getInt32(/*C=*/0)),
+ CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty));
+ CGF.FinishFunction();
+ return TaskEntry;
+}
+
+static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
+ SourceLocation Loc,
+ QualType KmpInt32Ty,
+ QualType KmpTaskTWithPrivatesPtrQTy,
+ QualType KmpTaskTWithPrivatesQTy) {
+ auto &C = CGM.getContext();
+ FunctionArgList Args;
+ ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
+ ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ Args.push_back(&GtidArg);
+ Args.push_back(&TaskTypeArg);
+ FunctionType::ExtInfo Info;
+ auto &DestructorFnInfo =
+ CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
+ /*isVariadic=*/false);
+ auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
+ auto *DestructorFn =
+ llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
+ ".omp_task_destructor.", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, DestructorFnInfo, DestructorFn);
+ CodeGenFunction CGF(CGM);
+ CGF.disableDebugInfo();
+ CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
+ Args);
+
+ auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
+ LValue Base =
+ CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
+ auto *KmpTaskTWithPrivatesQTyRD =
+ cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
+ auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
+ Base = CGF.EmitLValueForField(Base, *FI);
+ for (auto *Field :
+ cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
+ if (auto DtorKind = Field->getType().isDestructedType()) {
+ auto FieldLValue = CGF.EmitLValueForField(Base, Field);
+ CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
+ }
+ }
+ CGF.FinishFunction();
+ return DestructorFn;
+}
+
+/// \brief Emit a privates mapping function for correct handling of private and
+/// firstprivate variables.
+/// \code
+/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
+/// **noalias priv1,..., <tyn> **noalias privn) {
+/// *priv1 = &.privates.priv1;
+/// ...;
+/// *privn = &.privates.privn;
+/// }
+/// \endcode
+static llvm::Value *
+emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
+ const ArrayRef<const Expr *> PrivateVars,
+ const ArrayRef<const Expr *> FirstprivateVars,
+ QualType PrivatesQTy,
+ const ArrayRef<PrivateDataTy> Privates) {
+ auto &C = CGM.getContext();
+ FunctionArgList Args;
+ ImplicitParamDecl TaskPrivatesArg(
+ C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
+ C.getPointerType(PrivatesQTy).withConst().withRestrict());
+ Args.push_back(&TaskPrivatesArg);
+ llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
+ unsigned Counter = 1;
+ for (auto *E: PrivateVars) {
+ Args.push_back(ImplicitParamDecl::Create(
+ C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
+ .withConst()
+ .withRestrict()));
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ PrivateVarsPos[VD] = Counter;
+ ++Counter;
+ }
+ for (auto *E : FirstprivateVars) {
+ Args.push_back(ImplicitParamDecl::Create(
+ C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
+ .withConst()
+ .withRestrict()));
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ PrivateVarsPos[VD] = Counter;
+ ++Counter;
+ }
+ FunctionType::ExtInfo Info;
+ auto &TaskPrivatesMapFnInfo =
+ CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
+ /*isVariadic=*/false);
+ auto *TaskPrivatesMapTy =
+ CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
+ auto *TaskPrivatesMap = llvm::Function::Create(
+ TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
+ ".omp_task_privates_map.", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,
+ TaskPrivatesMap);
+ TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
+ CodeGenFunction CGF(CGM);
+ CGF.disableDebugInfo();
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
+ TaskPrivatesMapFnInfo, Args);
+
+ // *privi = &.privates.privi;
+ auto *TaskPrivatesArgAddr = CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(&TaskPrivatesArg), CGM.PointerAlignInBytes);
+ LValue Base =
+ CGF.MakeNaturalAlignAddrLValue(TaskPrivatesArgAddr, PrivatesQTy);
+ auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
+ Counter = 0;
+ for (auto *Field : PrivatesQTyRD->fields()) {
+ auto FieldLVal = CGF.EmitLValueForField(Base, Field);
+ auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
+ auto RefLVal = CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(VD),
+ VD->getType());
+ auto RefLoadRVal = CGF.EmitLoadOfLValue(RefLVal, Loc);
+ CGF.EmitStoreOfScalar(
+ FieldLVal.getAddress(),
+ CGF.MakeNaturalAlignAddrLValue(RefLoadRVal.getScalarVal(),
+ RefLVal.getType()->getPointeeType()));
+ ++Counter;
+ }
+ CGF.FinishFunction();
+ return TaskPrivatesMap;
}
-void CGOpenMPRuntime::EmitOMPFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
- SourceLocation Loc) {
- // Build call void __kmpc_flush(ident_t *loc, ...)
- // FIXME: List of variables is ignored by libiomp5 runtime, no need to
- // generate it, just request full memory fence.
- llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
- llvm::ConstantInt::get(CGM.Int32Ty, 0)};
- auto *RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_flush);
- CGF.EmitRuntimeCall(RTLFn, Args);
+static int array_pod_sort_comparator(const PrivateDataTy *P1,
+ const PrivateDataTy *P2) {
+ return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
+}
+
+void CGOpenMPRuntime::emitTaskCall(
+ CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
+ bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
+ llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
+ const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
+ ArrayRef<const Expr *> PrivateCopies,
+ ArrayRef<const Expr *> FirstprivateVars,
+ ArrayRef<const Expr *> FirstprivateCopies,
+ ArrayRef<const Expr *> FirstprivateInits,
+ ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
+ auto &C = CGM.getContext();
+ llvm::SmallVector<PrivateDataTy, 8> Privates;
+ // Aggregate privates and sort them by the alignment.
+ auto I = PrivateCopies.begin();
+ for (auto *E : PrivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.push_back(std::make_pair(
+ C.getTypeAlignInChars(VD->getType()),
+ PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
+ /*PrivateElemInit=*/nullptr)));
+ ++I;
+ }
+ I = FirstprivateCopies.begin();
+ auto IElemInitRef = FirstprivateInits.begin();
+ for (auto *E : FirstprivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.push_back(std::make_pair(
+ C.getTypeAlignInChars(VD->getType()),
+ PrivateHelpersTy(
+ VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
+ ++I, ++IElemInitRef;
+ }
+ llvm::array_pod_sort(Privates.begin(), Privates.end(),
+ array_pod_sort_comparator);
+ auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ // Build type kmp_routine_entry_t (if not built yet).
+ emitKmpRoutineEntryT(KmpInt32Ty);
+ // Build type kmp_task_t (if not built yet).
+ if (KmpTaskTQTy.isNull()) {
+ KmpTaskTQTy = C.getRecordType(
+ createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
+ }
+ auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
+ // Build particular struct kmp_task_t for the given task.
+ auto *KmpTaskTWithPrivatesQTyRD =
+ createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
+ auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
+ QualType KmpTaskTWithPrivatesPtrQTy =
+ C.getPointerType(KmpTaskTWithPrivatesQTy);
+ auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
+ auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
+ auto KmpTaskTWithPrivatesTySize =
+ CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy));
+ QualType SharedsPtrTy = C.getPointerType(SharedsTy);
+
+ // Emit initial values for private copies (if any).
+ llvm::Value *TaskPrivatesMap = nullptr;
+ auto *TaskPrivatesMapTy =
+ std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
+ 3)
+ ->getType();
+ if (!Privates.empty()) {
+ auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
+ TaskPrivatesMap = emitTaskPrivateMappingFunction(
+ CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
+ TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ TaskPrivatesMap, TaskPrivatesMapTy);
+ } else {
+ TaskPrivatesMap = llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(TaskPrivatesMapTy));
+ }
+ // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
+ // kmp_task_t *tt);
+ auto *TaskEntry = emitProxyTaskFunction(
+ CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
+ KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
+
+ // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
+ // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ // kmp_routine_entry_t *task_entry);
+ // Task flags. Format is taken from
+ // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
+ // description of kmp_tasking_flags struct.
+ const unsigned TiedFlag = 0x1;
+ const unsigned FinalFlag = 0x2;
+ unsigned Flags = Tied ? TiedFlag : 0;
+ auto *TaskFlags =
+ Final.getPointer()
+ ? CGF.Builder.CreateSelect(Final.getPointer(),
+ CGF.Builder.getInt32(FinalFlag),
+ CGF.Builder.getInt32(/*C=*/0))
+ : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
+ TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
+ auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
+ llvm::Value *AllocArgs[] = {
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags,
+ KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize),
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry,
+ KmpRoutineEntryPtrTy)};
+ auto *NewTask = CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
+ auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ NewTask, KmpTaskTWithPrivatesPtrTy);
+ LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
+ KmpTaskTWithPrivatesQTy);
+ LValue TDBase =
+ CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
+ // Fill the data in the resulting kmp_task_t record.
+ // Copy shareds if there are any.
+ llvm::Value *KmpTaskSharedsPtr = nullptr;
+ if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
+ KmpTaskSharedsPtr = CGF.EmitLoadOfScalar(
+ CGF.EmitLValueForField(
+ TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
+ Loc);
+ CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
+ }
+ // Emit initial values for private copies (if any).
+ bool NeedsCleanup = false;
+ if (!Privates.empty()) {
+ auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
+ auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
+ FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
+ LValue SharedsBase;
+ if (!FirstprivateVars.empty()) {
+ SharedsBase = CGF.MakeNaturalAlignAddrLValue(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
+ SharedsTy);
+ }
+ CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
+ cast<CapturedStmt>(*D.getAssociatedStmt()));
+ for (auto &&Pair : Privates) {
+ auto *VD = Pair.second.PrivateCopy;
+ auto *Init = VD->getAnyInitializer();
+ LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
+ if (Init) {
+ if (auto *Elem = Pair.second.PrivateElemInit) {
+ auto *OriginalVD = Pair.second.Original;
+ auto *SharedField = CapturesInfo.lookup(OriginalVD);
+ auto SharedRefLValue =
+ CGF.EmitLValueForField(SharedsBase, SharedField);
+ QualType Type = OriginalVD->getType();
+ if (Type->isArrayType()) {
+ // Initialize firstprivate array.
+ if (!isa<CXXConstructExpr>(Init) ||
+ CGF.isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
+ SharedRefLValue.getAddress(), Type);
+ } else {
+ // Initialize firstprivate array using element-by-element
+ // intialization.
+ CGF.EmitOMPAggregateAssign(
+ PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
+ Type, [&CGF, Elem, Init, &CapturesInfo](
+ llvm::Value *DestElement, llvm::Value *SrcElement) {
+ // Clean up any temporaries needed by the initialization.
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
+ return SrcElement;
+ });
+ (void)InitScope.Privatize();
+ // Emit initialization for single element.
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
+ CGF, &CapturesInfo);
+ CGF.EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer=*/false);
+ });
+ }
+ } else {
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(Elem, [SharedRefLValue]() -> llvm::Value *{
+ return SharedRefLValue.getAddress();
+ });
+ (void)InitScope.Privatize();
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue,
+ /*capturedByInit=*/false);
+ }
+ } else {
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ }
+ }
+ NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
+ ++FI;
+ }
+ }
+ // Provide pointer to function with destructors for privates.
+ llvm::Value *DestructorFn =
+ NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
+ KmpTaskTWithPrivatesPtrQTy,
+ KmpTaskTWithPrivatesQTy)
+ : llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
+ LValue Destructor = CGF.EmitLValueForField(
+ TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
+ CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ DestructorFn, KmpRoutineEntryPtrTy),
+ Destructor);
+
+ // Process list of dependences.
+ llvm::Value *DependInfo = nullptr;
+ unsigned DependencesNumber = Dependences.size();
+ if (!Dependences.empty()) {
+ // Dependence kind for RTL.
+ enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 };
+ enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
+ RecordDecl *KmpDependInfoRD;
+ QualType FlagsTy = C.getIntTypeForBitwidth(
+ C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false);
+ llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
+ if (KmpDependInfoTy.isNull()) {
+ KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
+ KmpDependInfoRD->startDefinition();
+ addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
+ addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
+ addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
+ KmpDependInfoRD->completeDefinition();
+ KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
+ } else {
+ KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
+ }
+ // Define type kmp_depend_info[<Dependences.size()>];
+ QualType KmpDependInfoArrayTy = C.getConstantArrayType(
+ KmpDependInfoTy, llvm::APInt(/*numBits=*/64, Dependences.size()),
+ ArrayType::Normal, /*IndexTypeQuals=*/0);
+ // kmp_depend_info[<Dependences.size()>] deps;
+ DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy);
+ for (unsigned i = 0; i < DependencesNumber; ++i) {
+ auto Addr = CGF.EmitLValue(Dependences[i].second);
+ auto *Size = llvm::ConstantInt::get(
+ CGF.SizeTy,
+ C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity());
+ auto Base = CGF.MakeNaturalAlignAddrLValue(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i),
+ KmpDependInfoTy);
+ // deps[i].base_addr = &<Dependences[i].second>;
+ auto BaseAddrLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
+ CGF.EmitStoreOfScalar(
+ CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy),
+ BaseAddrLVal);
+ // deps[i].len = sizeof(<Dependences[i].second>);
+ auto LenLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpDependInfoRD->field_begin(), Len));
+ CGF.EmitStoreOfScalar(Size, LenLVal);
+ // deps[i].flags = <Dependences[i].first>;
+ RTLDependenceKindTy DepKind;
+ switch (Dependences[i].first) {
+ case OMPC_DEPEND_in:
+ DepKind = DepIn;
+ break;
+ case OMPC_DEPEND_out:
+ DepKind = DepOut;
+ break;
+ case OMPC_DEPEND_inout:
+ DepKind = DepInOut;
+ break;
+ case OMPC_DEPEND_unknown:
+ llvm_unreachable("Unknown task dependence type");
+ }
+ auto FlagsLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
+ FlagsLVal);
+ }
+ DependInfo = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, 0),
+ CGF.VoidPtrTy);
+ }
+
+ // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
+ // libcall.
+ // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
+ // *new_task);
+ // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
+ // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
+ // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
+ // list is not empty
+ auto *ThreadID = getThreadID(CGF, Loc);
+ auto *UpLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *TaskArgs[] = {UpLoc, ThreadID, NewTask};
+ llvm::Value *DepTaskArgs[] = {
+ UpLoc,
+ ThreadID,
+ NewTask,
+ DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
+ DependInfo,
+ DependInfo ? CGF.Builder.getInt32(0) : nullptr,
+ DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
+ auto &&ThenCodeGen = [this, DependInfo, &TaskArgs,
+ &DepTaskArgs](CodeGenFunction &CGF) {
+ // TODO: add check for untied tasks.
+ CGF.EmitRuntimeCall(
+ createRuntimeFunction(DependInfo ? OMPRTL__kmpc_omp_task_with_deps
+ : OMPRTL__kmpc_omp_task),
+ DependInfo ? makeArrayRef(DepTaskArgs) : makeArrayRef(TaskArgs));
+ };
+ typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
+ IfCallEndCleanup;
+ llvm::Value *DepWaitTaskArgs[] = {
+ UpLoc,
+ ThreadID,
+ DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
+ DependInfo,
+ DependInfo ? CGF.Builder.getInt32(0) : nullptr,
+ DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
+ auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
+ DependInfo, &DepWaitTaskArgs](CodeGenFunction &CGF) {
+ CodeGenFunction::RunCleanupsScope LocalScope(CGF);
+ // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
+ // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
+ // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
+ // is specified.
+ if (DependInfo)
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
+ DepWaitTaskArgs);
+ // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
+ // kmp_task_t *new_task);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
+ TaskArgs);
+ // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
+ // kmp_task_t *new_task);
+ CGF.EHStack.pushCleanup<IfCallEndCleanup>(
+ NormalAndEHCleanup,
+ createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
+ llvm::makeArrayRef(TaskArgs));
+
+ // Call proxy_task_entry(gtid, new_task);
+ llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
+ CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
+ };
+ if (IfCond) {
+ emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
+ } else {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ ThenCodeGen(CGF);
+ }
}
+
+static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
+ llvm::Type *ArgsType,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps) {
+ auto &C = CGM.getContext();
+
+ // void reduction_func(void *LHSArg, void *RHSArg);
+ FunctionArgList Args;
+ ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
+ C.VoidPtrTy);
+ Args.push_back(&LHSArg);
+ Args.push_back(&RHSArg);
+ FunctionType::ExtInfo EI;
+ auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, Args, EI, /*isVariadic=*/false);
+ auto *Fn = llvm::Function::Create(
+ CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
+ ".omp.reduction.reduction_func", &CGM.getModule());
+ CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
+ CodeGenFunction CGF(CGM);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
+
+ // Dst = (void*[n])(LHSArg);
+ // Src = (void*[n])(RHSArg);
+ auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+ auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
+ CGF.PointerAlignInBytes),
+ ArgsType);
+
+ // ...
+ // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ // ...
+ CodeGenFunction::OMPPrivateScope Scope(CGF);
+ for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
+ Scope.addPrivate(
+ cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
+ [&]() -> llvm::Value *{
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
+ });
+ Scope.addPrivate(
+ cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
+ [&]() -> llvm::Value *{
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateAlignedLoad(
+ CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
+ CGM.PointerAlignInBytes),
+ CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
+ });
+ }
+ Scope.Privatize();
+ for (auto *E : ReductionOps) {
+ CGF.EmitIgnoredExpr(E);
+ }
+ Scope.ForceCleanup();
+ CGF.FinishFunction();
+ return Fn;
+}
+
+void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ bool WithNowait, bool SimpleReduction) {
+ // Next code should be emitted for reduction:
+ //
+ // static kmp_critical_name lock = { 0 };
+ //
+ // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
+ // ...
+ // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
+ // *(Type<n>-1*)rhs[<n>-1]);
+ // }
+ //
+ // ...
+ // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ // RedList, reduce_func, &<lock>)) {
+ // case 1:
+ // ...
+ // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ // ...
+ // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ // break;
+ // case 2:
+ // ...
+ // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ // ...
+ // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
+ // break;
+ // default:;
+ // }
+ //
+ // if SimpleReduction is true, only the next code is generated:
+ // ...
+ // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ // ...
+
+ auto &C = CGM.getContext();
+
+ if (SimpleReduction) {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ for (auto *E : ReductionOps) {
+ CGF.EmitIgnoredExpr(E);
+ }
+ return;
+ }
+
+ // 1. Build a list of reduction variables.
+ // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
+ llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
+ QualType ReductionArrayTy =
+ C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ auto *ReductionList =
+ CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
+ for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
+ auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
+ CGF.Builder.CreateAlignedStore(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
+ Elem, CGM.PointerAlignInBytes);
+ }
+
+ // 2. Emit reduce_func().
+ auto *ReductionFn = emitReductionFunction(
+ CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
+ RHSExprs, ReductionOps);
+
+ // 3. Create static kmp_critical_name lock = { 0 };
+ auto *Lock = getCriticalRegionLock(".reduction");
+
+ // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ // RedList, reduce_func, &<lock>);
+ auto *IdentTLoc = emitUpdateLocation(
+ CGF, Loc,
+ static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
+ auto *ThreadId = getThreadID(CGF, Loc);
+ auto *ReductionArrayTySize = llvm::ConstantInt::get(
+ CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
+ auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
+ CGF.VoidPtrTy);
+ llvm::Value *Args[] = {
+ IdentTLoc, // ident_t *<loc>
+ ThreadId, // i32 <gtid>
+ CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
+ ReductionArrayTySize, // size_type sizeof(RedList)
+ RL, // void *RedList
+ ReductionFn, // void (*) (void *, void *) <reduce_func>
+ Lock // kmp_critical_name *&<lock>
+ };
+ auto Res = CGF.EmitRuntimeCall(
+ createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
+ : OMPRTL__kmpc_reduce),
+ Args);
+
+ // 5. Build switch(res)
+ auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
+ auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
+
+ // 6. Build case 1:
+ // ...
+ // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ // ...
+ // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ // break;
+ auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
+ SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
+ CGF.EmitBlock(Case1BB);
+
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ llvm::Value *EndArgs[] = {
+ IdentTLoc, // ident_t *<loc>
+ ThreadId, // i32 <gtid>
+ Lock // kmp_critical_name *&<lock>
+ };
+ CGF.EHStack
+ .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
+ NormalAndEHCleanup,
+ createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
+ : OMPRTL__kmpc_end_reduce),
+ llvm::makeArrayRef(EndArgs));
+ for (auto *E : ReductionOps) {
+ CGF.EmitIgnoredExpr(E);
+ }
+ }
+
+ CGF.EmitBranch(DefaultBB);
+
+ // 7. Build case 2:
+ // ...
+ // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ // ...
+ // break;
+ auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
+ SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
+ CGF.EmitBlock(Case2BB);
+
+ {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ if (!WithNowait) {
+ // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
+ llvm::Value *EndArgs[] = {
+ IdentTLoc, // ident_t *<loc>
+ ThreadId, // i32 <gtid>
+ Lock // kmp_critical_name *&<lock>
+ };
+ CGF.EHStack
+ .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
+ NormalAndEHCleanup,
+ createRuntimeFunction(OMPRTL__kmpc_end_reduce),
+ llvm::makeArrayRef(EndArgs));
+ }
+ auto I = LHSExprs.begin();
+ for (auto *E : ReductionOps) {
+ const Expr *XExpr = nullptr;
+ const Expr *EExpr = nullptr;
+ const Expr *UpExpr = nullptr;
+ BinaryOperatorKind BO = BO_Comma;
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Assign) {
+ XExpr = BO->getLHS();
+ UpExpr = BO->getRHS();
+ }
+ }
+ // Try to emit update expression as a simple atomic.
+ auto *RHSExpr = UpExpr;
+ if (RHSExpr) {
+ // Analyze RHS part of the whole expression.
+ if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
+ RHSExpr->IgnoreParenImpCasts())) {
+ // If this is a conditional operator, analyze its condition for
+ // min/max reduction operator.
+ RHSExpr = ACO->getCond();
+ }
+ if (auto *BORHS =
+ dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
+ EExpr = BORHS->getRHS();
+ BO = BORHS->getOpcode();
+ }
+ }
+ if (XExpr) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
+ LValue X = CGF.EmitLValue(XExpr);
+ RValue E;
+ if (EExpr)
+ E = CGF.EmitAnyExpr(EExpr);
+ CGF.EmitOMPAtomicSimpleUpdateExpr(
+ X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
+ [&CGF, UpExpr, VD](RValue XRValue) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ PrivateScope.addPrivate(
+ VD, [&CGF, VD, XRValue]() -> llvm::Value *{
+ auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
+ CGF.EmitStoreThroughLValue(
+ XRValue,
+ CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
+ return LHSTemp;
+ });
+ (void)PrivateScope.Privatize();
+ return CGF.EmitAnyExpr(UpExpr);
+ });
+ } else {
+ // Emit as a critical region.
+ emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
+ CGF.EmitIgnoredExpr(E);
+ }, Loc);
+ }
+ ++I;
+ }
+ }
+
+ CGF.EmitBranch(DefaultBB);
+ CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
+}
+
+void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
+ // global_tid);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ // Ignore return result until untied tasks are supported.
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
+}
+
+void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
+ OpenMPDirectiveKind InnerKind,
+ const RegionCodeGenTy &CodeGen) {
+ InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind);
+ CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
+}
+
+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)
+ CancelKind = CancelLoop;
+ else if (CancelRegion == OMPD_sections)
+ CancelKind = CancelSections;
+ else {
+ 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(getCancellationKind(CancelRegion))};
+ // Ignore return result until untied tasks are supported.
+ auto *Result = CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
+ // if (__kmpc_cancellationpoint()) {
+ // __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);
+ }
+ }
+}
+
+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/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
index 6daf817..44bc8a1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
+#include "clang/AST/Type.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
@@ -42,9 +43,9 @@ namespace CodeGen {
class CodeGenFunction;
class CodeGenModule;
-class CGOpenMPRuntime {
-public:
+typedef llvm::function_ref<void(CodeGenFunction &)> RegionCodeGenTy;
+class CGOpenMPRuntime {
private:
enum OpenMPRTLFunction {
/// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
@@ -67,11 +68,9 @@ private:
// Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
// global_tid);
OMPRTL__kmpc_cancel_barrier,
- // Calls for static scheduling 'omp for' loops.
- OMPRTL__kmpc_for_static_init_4,
- OMPRTL__kmpc_for_static_init_4u,
- OMPRTL__kmpc_for_static_init_8,
- OMPRTL__kmpc_for_static_init_8u,
+ // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_barrier,
+ // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
OMPRTL__kmpc_for_static_fini,
// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
// global_tid);
@@ -82,12 +81,79 @@ private:
// Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 num_threads);
OMPRTL__kmpc_push_num_threads,
- // Call to void __kmpc_flush(ident_t *loc, ...);
+ // Call to void __kmpc_flush(ident_t *loc);
OMPRTL__kmpc_flush,
// Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
OMPRTL__kmpc_master,
// Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
OMPRTL__kmpc_end_master,
+ // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
+ // int end_part);
+ OMPRTL__kmpc_omp_taskyield,
+ // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
+ OMPRTL__kmpc_single,
+ // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
+ OMPRTL__kmpc_end_single,
+ // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
+ // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ // kmp_routine_entry_t *task_entry);
+ OMPRTL__kmpc_omp_task_alloc,
+ // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
+ // new_task);
+ OMPRTL__kmpc_omp_task,
+ // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
+ // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
+ // kmp_int32 didit);
+ OMPRTL__kmpc_copyprivate,
+ // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
+ // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
+ OMPRTL__kmpc_reduce,
+ // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
+ // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
+ // *lck);
+ OMPRTL__kmpc_reduce_nowait,
+ // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ OMPRTL__kmpc_end_reduce,
+ // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *lck);
+ OMPRTL__kmpc_end_reduce_nowait,
+ // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
+ // kmp_task_t * new_task);
+ OMPRTL__kmpc_omp_task_begin_if0,
+ // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
+ // kmp_task_t * new_task);
+ OMPRTL__kmpc_omp_task_complete_if0,
+ // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_ordered,
+ // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_end_ordered,
+ // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
+ // global_tid);
+ OMPRTL__kmpc_omp_taskwait,
+ // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_taskgroup,
+ // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_end_taskgroup,
+ // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
+ // int proc_bind);
+ OMPRTL__kmpc_push_proc_bind,
+ // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
+ // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
+ // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
+ OMPRTL__kmpc_omp_task_with_deps,
+ // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
+ // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
+ // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
+ OMPRTL__kmpc_omp_wait_deps,
+ // 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.
@@ -118,7 +184,7 @@ private:
/// \brief Map of flags and corresponding default locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
- llvm::Value *GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags);
+ llvm::Value *getOrCreateDefaultLocation(OpenMPLocationFlags Flags);
/// \brief Describes ident structure that describes a source location.
/// All descriptions are taken from
/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
@@ -186,13 +252,38 @@ private:
/// variables.
llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
InternalVars;
+ /// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
+ llvm::Type *KmpRoutineEntryPtrTy;
+ QualType KmpRoutineEntryPtrQTy;
+ /// \brief Type typedef struct kmp_task {
+ /// void * shareds; /**< pointer to block of pointers to
+ /// shared vars */
+ /// kmp_routine_entry_t routine; /**< pointer to routine to call for
+ /// executing task */
+ /// kmp_int32 part_id; /**< part id for the task */
+ /// kmp_routine_entry_t destructors; /* pointer to function to invoke
+ /// deconstructors of firstprivate C++ objects */
+ /// } kmp_task_t;
+ QualType KmpTaskTQTy;
+ /// \brief Type typedef struct kmp_depend_info {
+ /// kmp_intptr_t base_addr;
+ /// size_t len;
+ /// struct {
+ /// bool in:1;
+ /// bool out:1;
+ /// } flags;
+ /// } kmp_depend_info_t;
+ QualType KmpDependInfoTy;
+
+
+ /// \brief Build type kmp_routine_entry_t (if not built yet).
+ void emitKmpRoutineEntryT(QualType KmpInt32Ty);
/// \brief Emits object of ident_t type with info for source location.
/// \param Flags Flags for OpenMP location.
///
- llvm::Value *
- EmitOpenMPUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPLocationFlags Flags = OMP_IDENT_KMPC);
+ llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPLocationFlags Flags = OMP_IDENT_KMPC);
/// \brief Returns pointer to ident_t type.
llvm::Type *getIdentTyPointerTy();
@@ -203,7 +294,23 @@ private:
/// \brief Returns specified OpenMP runtime function.
/// \param Function OpenMP runtime function.
/// \return Specified function.
- llvm::Constant *CreateRuntimeFunction(OpenMPRTLFunction Function);
+ llvm::Constant *createRuntimeFunction(OpenMPRTLFunction Function);
+
+ /// \brief Returns __kmpc_for_static_init_* runtime function for the specified
+ /// size \a IVSize and sign \a IVSigned.
+ llvm::Constant *createForStaticInitFunction(unsigned IVSize, bool IVSigned);
+
+ /// \brief Returns __kmpc_dispatch_init_* runtime function for the specified
+ /// size \a IVSize and sign \a IVSigned.
+ llvm::Constant *createDispatchInitFunction(unsigned IVSize, bool IVSigned);
+
+ /// \brief Returns __kmpc_dispatch_next_* runtime function for the specified
+ /// size \a IVSize and sign \a IVSigned.
+ llvm::Constant *createDispatchNextFunction(unsigned IVSize, bool IVSigned);
+
+ /// \brief Returns __kmpc_dispatch_fini_* runtime function for the specified
+ /// size \a IVSize and sign \a IVSigned.
+ llvm::Constant *createDispatchFiniFunction(unsigned IVSize, bool IVSigned);
/// \brief If the specified mangled name is not in the module, create and
/// return threadprivate cache object. This object is a pointer's worth of
@@ -214,12 +321,12 @@ private:
/// \brief Emits address of the word in a memory where current thread id is
/// stored.
- virtual llvm::Value *EmitThreadIDAddress(CodeGenFunction &CGF,
+ virtual llvm::Value *emitThreadIDAddress(CodeGenFunction &CGF,
SourceLocation Loc);
/// \brief Gets thread id value for the current thread.
///
- llvm::Value *GetOpenMPThreadID(CodeGenFunction &CGF, SourceLocation Loc);
+ llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc);
/// \brief Gets (if variable with the given name already exist) or creates
/// internal global variable with the specified Name. The created variable has
@@ -227,7 +334,7 @@ private:
/// \param Ty Type of the global variable. If it is exist already the type
/// must be the same.
/// \param Name Name of the variable.
- llvm::Constant *GetOrCreateInternalVariable(llvm::Type *Ty,
+ llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
const llvm::Twine &Name);
/// \brief Set of threadprivate variables with the generated initializer.
@@ -239,78 +346,118 @@ private:
/// \param CopyCtor Pointer to a global copy function for \a VD.
/// \param Dtor Pointer to a global destructor function for \a VD.
/// \param Loc Location of threadprivate declaration.
- void EmitOMPThreadPrivateVarInit(CodeGenFunction &CGF, llvm::Value *VDAddr,
- llvm::Value *Ctor, llvm::Value *CopyCtor,
- llvm::Value *Dtor, SourceLocation Loc);
+ void emitThreadPrivateVarInit(CodeGenFunction &CGF, llvm::Value *VDAddr,
+ llvm::Value *Ctor, llvm::Value *CopyCtor,
+ llvm::Value *Dtor, SourceLocation Loc);
/// \brief Returns corresponding lock object for the specified critical region
/// name. If the lock object does not exist it is created, otherwise the
/// reference to the existing copy is returned.
/// \param CriticalName Name of the critical region.
///
- llvm::Value *GetCriticalRegionLock(StringRef CriticalName);
+ llvm::Value *getCriticalRegionLock(StringRef CriticalName);
public:
explicit CGOpenMPRuntime(CodeGenModule &CGM);
virtual ~CGOpenMPRuntime() {}
+ virtual void clear();
- /// \brief Emits outlined function for the specified OpenMP directive \a D
- /// (required for parallel and task directives). This outlined function has
- /// type void(*)(kmp_int32 /*ThreadID*/, kmp_int32 /*BoundID*/, struct
- /// context_vars*).
+ /// \brief Emits outlined function for the specified OpenMP parallel directive
+ /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
+ /// kmp_int32 BoundID, struct context_vars*).
+ /// \param D OpenMP directive.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ virtual llvm::Value *emitParallelOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
+
+ /// \brief Emits outlined function for the OpenMP task directive \a D. This
+ /// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32
+ /// PartID, struct context_vars*).
/// \param D OpenMP directive.
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
///
- virtual llvm::Value *
- EmitOpenMPOutlinedFunction(const OMPExecutableDirective &D,
- const VarDecl *ThreadIDVar);
+ virtual llvm::Value *emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
/// \brief Cleans up references to the objects in finished function.
///
- void FunctionFinished(CodeGenFunction &CGF);
+ void functionFinished(CodeGenFunction &CGF);
- /// \brief Emits code for parallel call of the \a OutlinedFn with variables
- /// captured in a record which address is stored in \a CapturedStruct.
+ /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// variables captured in a record which address is stored in \a
+ /// CapturedStruct.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
- /// this function is void(*)(kmp_int32, kmp_int32, struct context_vars*).
+ /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
/// \param CapturedStruct A pointer to the record with the references to
/// variables used in \a OutlinedFn function.
+ /// \param IfCond Condition in the associated 'if' clause, if it was
+ /// specified, nullptr otherwise.
///
- virtual void EmitOMPParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
- llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct);
-
- /// \brief Emits code for serial call of the \a OutlinedFn with variables
- /// captured in a record which address is stored in \a CapturedStruct.
- /// \param OutlinedFn Outlined function to be run in serial mode.
- /// \param CapturedStruct A pointer to the record with the references to
- /// variables used in \a OutlinedFn function.
- ///
- virtual void EmitOMPSerialCall(CodeGenFunction &CGF, SourceLocation Loc,
- llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct);
+ virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ llvm::Value *CapturedStruct,
+ const Expr *IfCond);
/// \brief Emits a critical region.
/// \param CriticalName Name of the critical region.
/// \param CriticalOpGen Generator for the statement associated with the given
/// critical region.
- virtual void EmitOMPCriticalRegion(CodeGenFunction &CGF,
- StringRef CriticalName,
- const std::function<void()> &CriticalOpGen,
- SourceLocation Loc);
+ virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen,
+ SourceLocation Loc);
/// \brief Emits a master region.
/// \param MasterOpGen Generator for the statement associated with the given
/// master region.
- virtual void EmitOMPMasterRegion(CodeGenFunction &CGF,
- const std::function<void()> &MasterOpGen,
+ virtual void emitMasterRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc);
+
+ /// \brief Emits code for a taskyield directive.
+ virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// \brief Emit a taskgroup region.
+ /// \param TaskgroupOpGen Generator for the statement associated with the
+ /// given taskgroup region.
+ virtual void emitTaskgroupRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &TaskgroupOpGen,
SourceLocation Loc);
- /// \brief Emits explicit barrier for OpenMP threads.
- /// \param IsExplicit true, if it is explicitly specified barrier.
+ /// \brief Emits a single region.
+ /// \param SingleOpGen Generator for the statement associated with the given
+ /// single region.
+ virtual void emitSingleRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &SingleOpGen,
+ SourceLocation Loc,
+ ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs,
+ ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> AssignmentOps);
+
+ /// \brief Emit an ordered region.
+ /// \param OrderedOpGen Generator for the statement associated with the given
+ /// ordered region.
+ virtual void emitOrderedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &OrderedOpGen,
+ SourceLocation Loc);
+
+ /// \brief Emit an implicit/explicit barrier for OpenMP threads.
+ /// \param Kind Directive for which this implicit barrier call must be
+ /// generated. Must be OMPD_barrier for explicit barrier generation.
+ /// \param CheckForCancel true if check for possible cancellation must be
+ /// performed, false otherwise.
///
- virtual void EmitOMPBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
- bool IsExplicit = true);
+ virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind,
+ bool CheckForCancel = true);
/// \brief Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of worksharing directive is emitted without outer loop.
@@ -320,6 +467,12 @@ public:
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked) const;
+ /// \brief Check if the specified \a ScheduleKind is dynamic.
+ /// This kind of worksharing directive is emitted without outer loop.
+ /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
+ ///
+ virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
+
/// \brief Call the appropriate runtime routine to initialize it before start
/// of loop.
///
@@ -332,6 +485,7 @@ public:
/// \param SchedKind Schedule kind, specified by the 'schedule' clause.
/// \param IVSize Size of the iteration variable in bits.
/// \param IVSigned Sign of the interation variable.
+ /// \param Ordered true if loop is ordered, false otherwise.
/// \param IL Address of the output variable in which the flag of the
/// last iteration is returned.
/// \param LB Address of the output variable in which the lower iteration
@@ -343,29 +497,64 @@ public:
/// \param Chunk Value of the chunk for the static_chunked scheduled loop.
/// For the default (nullptr) value, the chunk 1 will be used.
///
- virtual void EmitOMPForInit(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind SchedKind,
- unsigned IVSize, bool IVSigned, llvm::Value *IL,
- llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
- llvm::Value *Chunk = nullptr);
+ virtual void emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPScheduleClauseKind SchedKind, unsigned IVSize,
+ bool IVSigned, bool Ordered, llvm::Value *IL,
+ llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
+ llvm::Value *Chunk = nullptr);
+
+ /// \brief Call the appropriate runtime routine to notify that we finished
+ /// iteration of the ordered loop with the dynamic scheduling.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the interation variable.
+ ///
+ virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF,
+ SourceLocation Loc, unsigned IVSize,
+ bool IVSigned);
/// \brief Call the appropriate runtime routine to notify that we finished
/// all the work with current loop.
///
/// \param CGF Reference to current CodeGenFunction.
/// \param Loc Clang source location.
- /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
///
- virtual void EmitOMPForFinish(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind ScheduleKind);
+ virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// Call __kmpc_dispatch_next(
+ /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
+ /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
+ /// kmp_int[32|64] *p_stride);
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the interation variable.
+ /// \param IL Address of the output variable in which the flag of the
+ /// last iteration is returned.
+ /// \param LB Address of the output variable in which the lower iteration
+ /// number is returned.
+ /// \param UB Address of the output variable in which the upper iteration
+ /// number is returned.
+ /// \param ST Address of the output variable in which the stride value is
+ /// returned.
+ virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
+ unsigned IVSize, bool IVSigned,
+ llvm::Value *IL, llvm::Value *LB,
+ llvm::Value *UB, llvm::Value *ST);
/// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
/// clause.
/// \param NumThreads An integer value of threads.
- virtual void EmitOMPNumThreadsClause(CodeGenFunction &CGF,
- llvm::Value *NumThreads,
- SourceLocation Loc);
+ virtual void emitNumThreadsClause(CodeGenFunction &CGF,
+ llvm::Value *NumThreads,
+ SourceLocation Loc);
+
+ /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
+ /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
+ virtual void emitProcBindClause(CodeGenFunction &CGF,
+ OpenMPProcBindClauseKind ProcBind,
+ SourceLocation Loc);
/// \brief Returns address of the threadprivate variable for the current
/// thread.
@@ -373,10 +562,10 @@ public:
/// \param VDAddr Address of the global variable \a VD.
/// \param Loc Location of the reference to threadprivate var.
/// \return Address of the threadprivate variable for the current thread.
- virtual llvm::Value *getOMPAddrOfThreadPrivate(CodeGenFunction &CGF,
- const VarDecl *VD,
- llvm::Value *VDAddr,
- SourceLocation Loc);
+ virtual llvm::Value *getAddrOfThreadPrivate(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ llvm::Value *VDAddr,
+ SourceLocation Loc);
/// \brief Emit a code for initialization of threadprivate variable. It emits
/// a call to runtime library which adds initial value to the newly created
@@ -387,15 +576,139 @@ public:
/// \param Loc Location of threadprivate declaration.
/// \param PerformInit true if initialization expression is not constant.
virtual llvm::Function *
- EmitOMPThreadPrivateVarDefinition(const VarDecl *VD, llvm::Value *VDAddr,
- SourceLocation Loc, bool PerformInit,
- CodeGenFunction *CGF = nullptr);
+ emitThreadPrivateVarDefinition(const VarDecl *VD, llvm::Value *VDAddr,
+ SourceLocation Loc, bool PerformInit,
+ CodeGenFunction *CGF = nullptr);
/// \brief Emit flush of the variables specified in 'omp flush' directive.
/// \param Vars List of variables to flush.
- virtual void EmitOMPFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
- SourceLocation Loc);
+ virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
+ SourceLocation Loc);
+
+ /// \brief Emit task region for the task directive. The task region is
+ /// emitted in several steps:
+ /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
+ /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
+ /// function:
+ /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+ /// TaskFunction(gtid, tt->part_id, tt->shareds);
+ /// return 0;
+ /// }
+ /// 2. Copy a list of shared variables to field shareds of the resulting
+ /// structure kmp_task_t returned by the previous call (if any).
+ /// 3. Copy a pointer to destructions function to field destructions of the
+ /// resulting structure kmp_task_t.
+ /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
+ /// kmp_task_t *new_task), where new_task is a resulting structure from
+ /// previous items.
+ /// \param D Current task directive.
+ /// \param Tied true if the task is tied (the task is tied to the thread that
+ /// can suspend its task region), false - untied (the task is not tied to any
+ /// thread).
+ /// \param Final Contains either constant bool value, or llvm::Value * of i1
+ /// type for final clause. If the value is true, the task forces all of its
+ /// child tasks to become final and included tasks.
+ /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
+ /// /*part_id*/, captured_struct */*__context*/);
+ /// \param SharedsTy A type which contains references the shared variables.
+ /// \param Shareds Context with the list of shared variables from the \p
+ /// TaskFunction.
+ /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
+ /// otherwise.
+ /// \param PrivateVars List of references to private variables for the task
+ /// directive.
+ /// \param PrivateCopies List of private copies for each private variable in
+ /// \p PrivateVars.
+ /// \param FirstprivateVars List of references to private variables for the
+ /// task directive.
+ /// \param FirstprivateCopies List of private copies for each private variable
+ /// in \p FirstprivateVars.
+ /// \param FirstprivateInits List of references to auto generated variables
+ /// used for initialization of a single array element. Used if firstprivate
+ /// variable is of array type.
+ /// \param Dependences List of dependences for the 'task' construct, including
+ /// original expression and dependency type.
+ virtual void emitTaskCall(
+ CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
+ bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
+ llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
+ const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
+ ArrayRef<const Expr *> PrivateCopies,
+ ArrayRef<const Expr *> FirstprivateVars,
+ ArrayRef<const Expr *> FirstprivateCopies,
+ ArrayRef<const Expr *> FirstprivateInits,
+ ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences);
+
+ /// \brief Emit code for the directive that does not require outlining.
+ ///
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ virtual void emitInlinedDirective(CodeGenFunction &CGF,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen);
+ /// \brief Emit a code for reduction clause. Next code should be emitted for
+ /// reduction:
+ /// \code
+ ///
+ /// static kmp_critical_name lock = { 0 };
+ ///
+ /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ /// ...
+ /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ /// ...
+ /// }
+ ///
+ /// ...
+ /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ /// RedList, reduce_func, &<lock>)) {
+ /// case 1:
+ /// ...
+ /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ /// ...
+ /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ /// break;
+ /// case 2:
+ /// ...
+ /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ /// ...
+ /// break;
+ /// default:;
+ /// }
+ /// \endcode
+ ///
+ /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
+ /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
+ /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
+ /// or 'operator binop(LHS, RHS)'.
+ /// \param WithNowait true if parent directive has also nowait clause, false
+ /// otherwise.
+ virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ bool WithNowait, bool SimpleReduction);
+
+ /// \brief Emit code for 'taskwait' directive.
+ virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// \brief Emit code for 'cancellation point' construct.
+ /// \param CancelRegion Region kind for which the cancellation point must be
+ /// emitted.
+ ///
+ 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
} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
index 2de0b2f..d4ad33e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
+++ b/contrib/llvm/tools/clang/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
@@ -109,8 +109,8 @@ struct CGBitFieldInfo {
class CGRecordLayout {
friend class CodeGenTypes;
- CGRecordLayout(const CGRecordLayout &) LLVM_DELETED_FUNCTION;
- void operator=(const CGRecordLayout &) LLVM_DELETED_FUNCTION;
+ CGRecordLayout(const CGRecordLayout &) = delete;
+ void operator=(const CGRecordLayout &) = delete;
private:
/// The LLVM type corresponding to this record layout; used when
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 7ad394b..f91eceb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -99,10 +99,25 @@ struct CGRecordLowering {
MemberInfo StorageInfo(CharUnits Offset, llvm::Type *Data) {
return MemberInfo(Offset, MemberInfo::Field, Data);
}
- bool useMSABI() {
+
+ /// The Microsoft bitfield layout rule allocates discrete storage
+ /// units of the field's formal type and only combines adjacent
+ /// fields of the same formal type. We want to emit a layout with
+ /// these discrete storage units instead of combining them into a
+ /// continuous run.
+ bool isDiscreteBitFieldABI() {
return Context.getTargetInfo().getCXXABI().isMicrosoft() ||
D->isMsStruct(Context);
}
+
+ /// The Itanium base layout rule allows virtual bases to overlap
+ /// other bases, which complicates layout in specific ways.
+ ///
+ /// Note specifically that the ms_struct attribute doesn't change this.
+ bool isOverlappingVBaseABI() {
+ return !Context.getTargetInfo().getCXXABI().isMicrosoft();
+ }
+
/// \brief Wraps llvm::Type::getIntNTy with some implicit arguments.
llvm::Type *getIntNType(uint64_t NumBits) {
return llvm::Type::getIntNTy(Types.getLLVMContext(),
@@ -119,8 +134,9 @@ struct CGRecordLowering {
/// for itanium bitfields that are smaller than their declared type.
llvm::Type *getStorageType(const FieldDecl *FD) {
llvm::Type *Type = Types.ConvertTypeForMem(FD->getType());
- return useMSABI() || !FD->isBitField() ? Type :
- getIntNType(std::min(FD->getBitWidthValue(Context),
+ if (!FD->isBitField()) return Type;
+ if (isDiscreteBitFieldABI()) return Type;
+ return getIntNType(std::min(FD->getBitWidthValue(Context),
(unsigned)Context.toBits(getSize(Type))));
}
/// \brief Gets the llvm Basesubobject type from a CXXRecordDecl.
@@ -137,15 +153,10 @@ struct CGRecordLowering {
return CharUnits::fromQuantity(DataLayout.getABITypeAlignment(Type));
}
bool isZeroInitializable(const FieldDecl *FD) {
- const Type *Type = FD->getType()->getBaseElementTypeUnsafe();
- if (const MemberPointerType *MPT = Type->getAs<MemberPointerType>())
- return Types.getCXXABI().isZeroInitializable(MPT);
- if (const RecordType *RT = Type->getAs<RecordType>())
- return isZeroInitializable(RT->getDecl());
- return true;
+ return Types.isZeroInitializable(FD->getType());
}
bool isZeroInitializable(const RecordDecl *RD) {
- return Types.getCGRecordLayout(RD).isZeroInitializable();
+ return Types.isZeroInitializable(RD);
}
void appendPaddingBytes(CharUnits Size) {
if (!Size.isZero())
@@ -198,8 +209,8 @@ struct CGRecordLowering {
bool IsZeroInitializableAsBase : 1;
bool Packed : 1;
private:
- CGRecordLowering(const CGRecordLowering &) LLVM_DELETED_FUNCTION;
- void operator =(const CGRecordLowering &) LLVM_DELETED_FUNCTION;
+ CGRecordLowering(const CGRecordLowering &) = delete;
+ void operator =(const CGRecordLowering &) = delete;
};
} // namespace {
@@ -217,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
@@ -303,9 +310,13 @@ void CGRecordLowering::lowerUnion() {
// If this is the case, then we aught not to try and come up with a "better"
// type, it might not be very easy to come up with a Constant which
// correctly initializes it.
- if (!SeenNamedMember && Field->getDeclName()) {
- SeenNamedMember = true;
- if (!isZeroInitializable(Field)) {
+ if (!SeenNamedMember) {
+ SeenNamedMember = Field->getIdentifier();
+ if (!SeenNamedMember)
+ if (const auto *FieldRD =
+ dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
+ SeenNamedMember = FieldRD->findFirstNamedDataMember();
+ if (SeenNamedMember && !isZeroInitializable(Field)) {
IsZeroInitializable = IsZeroInitializableAsBase = false;
StorageType = FieldType;
}
@@ -365,7 +376,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
// used to determine if the ASTRecordLayout is treating these two bitfields as
// contiguous. StartBitOffset is offset of the beginning of the Run.
uint64_t StartBitOffset, Tail = 0;
- if (useMSABI()) {
+ if (isDiscreteBitFieldABI()) {
for (; Field != FieldEnd; ++Field) {
uint64_t BitOffset = getFieldBitOffset(*Field);
// Zero-width bitfields end runs.
@@ -438,8 +449,12 @@ void CGRecordLowering::accumulateBases() {
for (const auto &Base : RD->bases()) {
if (Base.isVirtual())
continue;
+
+ // Bases can be zero-sized even if not technically empty if they
+ // contain only a trailing array member.
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
- if (!BaseDecl->isEmpty())
+ if (!BaseDecl->isEmpty() &&
+ !Context.getASTRecordLayout(BaseDecl).getSize().isZero())
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
}
@@ -461,7 +476,7 @@ void CGRecordLowering::accumulateVBases() {
// smaller than the nvsize. Here we check to see if such a base is placed
// before the nvsize and set the scissor offset to that, instead of the
// nvsize.
- if (!useMSABI())
+ if (isOverlappingVBaseABI())
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (BaseDecl->isEmpty())
@@ -482,7 +497,8 @@ void CGRecordLowering::accumulateVBases() {
CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl);
// If the vbase is a primary virtual base of some base, then it doesn't
// get its own storage location but instead lives inside of that base.
- if (!useMSABI() && Context.isNearlyEmpty(BaseDecl) &&
+ if (isOverlappingVBaseABI() &&
+ Context.isNearlyEmpty(BaseDecl) &&
!hasOwnStorage(RD, BaseDecl)) {
Members.push_back(MemberInfo(Offset, MemberInfo::VBase, nullptr,
BaseDecl));
@@ -631,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.
@@ -663,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,
@@ -836,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/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
index e3bdf86..7a0b8a3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
@@ -88,6 +88,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::ContinueStmtClass:
case Stmt::DefaultStmtClass:
case Stmt::CaseStmtClass:
+ case Stmt::SEHLeaveStmtClass:
llvm_unreachable("should have emitted these statements as simple");
#define STMT(Type, Base)
@@ -173,9 +174,6 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
- case Stmt::SEHLeaveStmtClass:
- EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
- break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
@@ -224,6 +222,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPTaskwaitDirectiveClass:
EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S));
break;
+ case Stmt::OMPTaskgroupDirectiveClass:
+ EmitOMPTaskgroupDirective(cast<OMPTaskgroupDirective>(*S));
+ break;
case Stmt::OMPFlushDirectiveClass:
EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));
break;
@@ -239,6 +240,12 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPTeamsDirectiveClass:
EmitOMPTeamsDirective(cast<OMPTeamsDirective>(*S));
break;
+ case Stmt::OMPCancellationPointDirectiveClass:
+ EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S));
+ break;
+ case Stmt::OMPCancelDirectiveClass:
+ EmitOMPCancelDirective(cast<OMPCancelDirective>(*S));
+ break;
}
}
@@ -256,6 +263,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
+ case Stmt::SEHLeaveStmtClass: EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S)); break;
}
return true;
@@ -424,9 +432,8 @@ void CodeGenFunction::EmitLabel(const LabelDecl *D) {
ResolveBranchFixups(Dest.getBlock());
}
- RegionCounter Cnt = getPGORegionCounter(D->getStmt());
EmitBlock(Dest.getBlock());
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(D->getStmt());
}
/// Change the cleanup scope of the labels in this lexical scope to
@@ -514,7 +521,6 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// C99 6.8.4.1: The first substatement is executed if the expression compares
// unequal to 0. The condition must be a scalar type.
LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
- RegionCounter Cnt = getPGORegionCounter(&S);
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
@@ -533,7 +539,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// This avoids emitting dead code and simplifies the CFG substantially.
if (!ContainsLabel(Skipped)) {
if (CondConstant)
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
if (Executed) {
RunCleanupsScope ExecutedScope(*this);
EmitStmt(Executed);
@@ -550,11 +556,12 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
if (S.getElse())
ElseBlock = createBasicBlock("if.else");
- EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, Cnt.getCount());
+ EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock,
+ getProfileCount(S.getThen()));
// Emit the 'then' code.
EmitBlock(ThenBlock);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
{
RunCleanupsScope ThenScope(*this);
EmitStmt(S.getThen());
@@ -564,8 +571,8 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// Emit the 'else' code if present.
if (const Stmt *Else = S.getElse()) {
{
- // There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(*this);
+ // There is no need to emit line number for an unconditional branch.
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBlock(ElseBlock);
}
{
@@ -573,8 +580,8 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitStmt(Else);
}
{
- // There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(*this);
+ // There is no need to emit line number for an unconditional branch.
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBranch(ContBlock);
}
}
@@ -679,14 +686,12 @@ void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> WhileAttrs) {
- RegionCounter Cnt = getPGORegionCounter(&S);
-
// Emit the header for the loop, which will also become
// the continue target.
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
- LoopStack.push(LoopHeader.getBlock());
+ LoopStack.push(LoopHeader.getBlock(), WhileAttrs);
// Create an exit block for when the condition fails, which will
// also become the break target.
@@ -725,9 +730,9 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- llvm::BranchInst *CondBr =
- Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ BoolCondVal, LoopBody, ExitBlock,
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -743,7 +748,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
{
RunCleanupsScope BodyScope(*this);
EmitBlock(LoopBody);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
EmitStmt(S.getBody());
}
@@ -772,7 +777,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
JumpDest LoopExit = getJumpDestInCurrentScope("do.end");
JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");
- RegionCounter Cnt = getPGORegionCounter(&S);
+ uint64_t ParentCount = getCurrentProfileCount();
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));
@@ -780,9 +785,9 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
- LoopStack.push(LoopBody);
+ LoopStack.push(LoopBody, DoAttrs);
- EmitBlockWithFallThrough(LoopBody, Cnt);
+ EmitBlockWithFallThrough(LoopBody, &S);
{
RunCleanupsScope BodyScope(*this);
EmitStmt(S.getBody());
@@ -809,9 +814,10 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
- llvm::BranchInst *CondBr =
- Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
- PGO.createLoopWeights(S.getCond(), Cnt));
+ uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount;
+ llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ BoolCondVal, LoopBody, LoopExit.getBlock(),
+ createProfileWeightsForLoop(S.getCond(), BackedgeCount));
// Attach metadata to loop body conditional branch.
EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);
@@ -838,8 +844,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
if (S.getInit())
EmitStmt(S.getInit());
- RegionCounter Cnt = getPGORegionCounter(&S);
-
// Start the loop with a block that tests the condition.
// If there's an increment, the continue scope will be overwritten
// later.
@@ -847,7 +851,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
- LoopStack.push(CondBlock);
+ LoopStack.push(CondBlock, ForAttrs);
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
@@ -881,9 +885,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::BranchInst *CondBr =
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ BoolCondVal, ForBody, ExitBlock,
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
// Attach metadata to loop body conditional branch.
EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
@@ -898,7 +902,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// Treat it as a non-zero constant. Don't even create a new block for the
// body, just fall into it.
}
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
{
// Create a separate cleanup scope for the body, in case it is not
@@ -939,15 +943,13 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
EmitStmt(S.getRangeStmt());
EmitStmt(S.getBeginEndStmt());
- RegionCounter Cnt = getPGORegionCounter(&S);
-
// Start the loop with a block that tests the condition.
// If there's an increment, the continue scope will be overwritten
// later.
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock);
+ LoopStack.push(CondBlock, ForAttrs);
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
@@ -962,7 +964,8 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
llvm::BranchInst *CondBr = Builder.CreateCondBr(
- BoolCondVal, ForBody, ExitBlock, PGO.createLoopWeights(S.getCond(), Cnt));
+ BoolCondVal, ForBody, ExitBlock,
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
// Attach metadata to loop body conditional branch.
EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
@@ -973,7 +976,7 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
}
EmitBlock(ForBody);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
// Create a block for the increment. In case of a 'continue', we jump there.
JumpDest Continue = getJumpDestInCurrentScope("for.inc");
@@ -1022,6 +1025,12 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+ // Returning from an outlined SEH helper is UB, and we already warn on it.
+ if (IsOutlinedSEHHelper) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ }
+
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
@@ -1133,13 +1142,11 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext());
llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext());
- RegionCounter CaseCnt = getPGORegionCounter(&S);
-
// Emit the code for this case. We do this first to make sure it is
// properly chained from our predecessor before generating the
// switch machinery to enter this block.
llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
- EmitBlockWithFallThrough(CaseDest, CaseCnt);
+ EmitBlockWithFallThrough(CaseDest, &S);
EmitStmt(S.getSubStmt());
// If range is empty, do nothing.
@@ -1150,7 +1157,7 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
// FIXME: parameters such as this should not be hardcoded.
if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
// Range is small enough to add multiple switch instruction cases.
- uint64_t Total = CaseCnt.getCount();
+ uint64_t Total = getProfileCount(&S);
unsigned NCases = Range.getZExtValue() + 1;
// We only have one region counter for the entire set of cases here, so we
// need to divide the weights evenly between the generated cases, ensuring
@@ -1189,9 +1196,9 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
llvm::MDNode *Weights = nullptr;
if (SwitchWeights) {
- uint64_t ThisCount = CaseCnt.getCount();
+ uint64_t ThisCount = getProfileCount(&S);
uint64_t DefaultCount = (*SwitchWeights)[0];
- Weights = PGO.createBranchWeights(ThisCount, DefaultCount);
+ Weights = createProfileWeights(ThisCount, DefaultCount);
// Since we're chaining the switch default through each large case range, we
// need to update the weight for the default, ie, the first case, to include
@@ -1224,7 +1231,6 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
return;
}
- RegionCounter CaseCnt = getPGORegionCounter(&S);
llvm::ConstantInt *CaseVal =
Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext()));
@@ -1239,7 +1245,7 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
// Only do this optimization if there are no cleanups that need emitting.
if (isObviouslyBranchWithoutCleanups(Block)) {
if (SwitchWeights)
- SwitchWeights->push_back(CaseCnt.getCount());
+ SwitchWeights->push_back(getProfileCount(&S));
SwitchInsn->addCase(CaseVal, Block.getBlock());
// If there was a fallthrough into this case, make sure to redirect it to
@@ -1253,9 +1259,9 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
}
llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
- EmitBlockWithFallThrough(CaseDest, CaseCnt);
+ EmitBlockWithFallThrough(CaseDest, &S);
if (SwitchWeights)
- SwitchWeights->push_back(CaseCnt.getCount());
+ SwitchWeights->push_back(getProfileCount(&S));
SwitchInsn->addCase(CaseVal, CaseDest);
// Recursively emitting the statement is acceptable, but is not wonderful for
@@ -1276,12 +1282,11 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
llvm::ConstantInt *CaseVal =
Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext()));
- CaseCnt = getPGORegionCounter(NextCase);
if (SwitchWeights)
- SwitchWeights->push_back(CaseCnt.getCount());
+ SwitchWeights->push_back(getProfileCount(NextCase));
if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
CaseDest = createBasicBlock("sw.bb");
- EmitBlockWithFallThrough(CaseDest, CaseCnt);
+ EmitBlockWithFallThrough(CaseDest, &S);
}
SwitchInsn->addCase(CaseVal, CaseDest);
@@ -1297,8 +1302,7 @@ void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) {
assert(DefaultBlock->empty() &&
"EmitDefaultStmt: Default block already defined?");
- RegionCounter Cnt = getPGORegionCounter(&S);
- EmitBlockWithFallThrough(DefaultBlock, Cnt);
+ EmitBlockWithFallThrough(DefaultBlock, &S);
EmitStmt(S.getSubStmt());
}
@@ -1520,10 +1524,8 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
const SwitchCase *Case = nullptr;
if (FindCaseStatementsForValue(S, ConstantCondValue, CaseStmts,
getContext(), Case)) {
- if (Case) {
- RegionCounter CaseCnt = getPGORegionCounter(Case);
- CaseCnt.beginRegion(Builder);
- }
+ if (Case)
+ incrementProfileCounter(Case);
RunCleanupsScope ExecutedScope(*this);
// Emit the condition variable if needed inside the entire cleanup scope
@@ -1540,8 +1542,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// specified series of statements and we're good.
for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
EmitStmt(CaseStmts[i]);
- RegionCounter ExitCnt = getPGORegionCounter(&S);
- ExitCnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
// Now we want to restore the saved switch instance so that nested
// switches continue to function properly
@@ -1572,7 +1573,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
Case;
Case = Case->getNextSwitchCase()) {
if (isa<DefaultStmt>(Case))
- DefaultCount = getPGORegionCounter(Case).getCount();
+ DefaultCount = getProfileCount(Case);
NumCases += 1;
}
SwitchWeights = new SmallVector<uint64_t, 16>();
@@ -1621,8 +1622,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// Emit continuation.
EmitBlock(SwitchExit.getBlock(), true);
- RegionCounter ExitCnt = getPGORegionCounter(&S);
- ExitCnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
if (SwitchWeights) {
assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
@@ -1630,7 +1630,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// If there's only one jump destination there's no sense weighting it.
if (SwitchWeights->size() > 1)
SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
- PGO.createBranchWeights(*SwitchWeights));
+ createProfileWeights(*SwitchWeights));
delete SwitchWeights;
}
SwitchInsn = SavedSwitchInsn;
@@ -1696,7 +1696,7 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
static std::string
AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr,
const TargetInfo &Target, CodeGenModule &CGM,
- const AsmStmt &Stmt) {
+ const AsmStmt &Stmt, const bool EarlyClobber) {
const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
if (!AsmDeclRef)
return Constraint;
@@ -1721,7 +1721,7 @@ AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr,
}
// Canonicalize the register here before returning it.
Register = Target.getNormalizedGCCRegisterName(Register);
- return "{" + Register.str() + "}";
+ return (EarlyClobber ? "&{" : "{") + Register.str() + "}";
}
llvm::Value*
@@ -1759,6 +1759,16 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
const Expr *InputExpr,
std::string &ConstraintStr) {
+ // If this can't be a register or memory, i.e., has to be a constant
+ // (immediate or symbolic), try to emit it as such.
+ if (!Info.allowsRegister() && !Info.allowsMemory()) {
+ llvm::APSInt Result;
+ if (InputExpr->EvaluateAsInt(Result, getContext()))
+ return llvm::ConstantInt::get(getLLVMContext(), Result);
+ assert(!Info.requiresImmediateConstant() &&
+ "Required-immediate inlineasm arg isn't constant?");
+ }
+
if (Info.allowsRegister() || !Info.allowsMemory())
if (CodeGenFunction::hasScalarEvaluationKind(InputExpr->getType()))
return EmitScalarExpr(InputExpr);
@@ -1842,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];
@@ -1854,7 +1872,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr,
- getTarget(), CGM, S);
+ getTarget(), CGM, S,
+ Info.earlyClobber());
LValue Dest = EmitLValue(OutExpr);
if (!Constraints.empty())
@@ -1904,6 +1923,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Args.push_back(Dest.getAddress());
Constraints += "=*";
Constraints += OutputConstraint;
+ ReadOnly = ReadNone = false;
}
if (Info.isReadWrite()) {
@@ -1948,6 +1968,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+ if (Info.allowsMemory())
+ ReadNone = false;
+
if (!Constraints.empty())
Constraints += ',';
@@ -1956,10 +1979,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
InputConstraint = SimplifyConstraint(InputConstraint.c_str(), getTarget(),
&OutputConstraintInfos);
- InputConstraint =
- AddVariableConstraints(InputConstraint,
- *InputExpr->IgnoreParenNoopCasts(getContext()),
- getTarget(), CGM, S);
+ InputConstraint = AddVariableConstraints(
+ InputConstraint, *InputExpr->IgnoreParenNoopCasts(getContext()),
+ getTarget(), CGM, S, false /* No EarlyClobber */);
llvm::Value *Arg = EmitAsmInput(Info, InputExpr, Constraints);
@@ -2013,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())
@@ -2053,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)) {
@@ -2145,7 +2179,7 @@ CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
// Emit the CapturedDecl
CodeGenFunction CGF(CGM, true);
- CGF.CapturedStmtInfo = new CGCapturedStmtInfo(S, K);
+ CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K));
llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
delete CGF.CapturedStmtInfo;
@@ -2187,6 +2221,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
CapturedStmtInfo->getHelperName(), &CGM.getModule());
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
+ if (CD->isNothrow())
+ F->addFnAttr(llvm::Attribute::NoUnwind);
// Generate the function.
StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 78fd37c..a1f093a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -20,288 +20,527 @@
using namespace clang;
using namespace CodeGen;
-namespace {
-/// \brief RAII for emitting code of CapturedStmt without function outlining.
-class InlinedOpenMPRegion {
- CodeGenFunction &CGF;
- CodeGenFunction::CGCapturedStmtInfo *PrevCapturedStmtInfo;
- const Decl *StoredCurCodeDecl;
-
- /// \brief A class to emit CapturedStmt construct as inlined statement without
- /// generating a function for outlined code.
- class CGInlinedOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
- public:
- CGInlinedOpenMPRegionInfo() : CGCapturedStmtInfo() {}
- };
-
-public:
- InlinedOpenMPRegion(CodeGenFunction &CGF, const Stmt *S)
- : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo),
- StoredCurCodeDecl(CGF.CurCodeDecl) {
- CGF.CurCodeDecl = cast<CapturedStmt>(S)->getCapturedDecl();
- CGF.CapturedStmtInfo = new CGInlinedOpenMPRegionInfo();
- }
- ~InlinedOpenMPRegion() {
- delete CGF.CapturedStmtInfo;
- CGF.CapturedStmtInfo = PrevCapturedStmtInfo;
- CGF.CurCodeDecl = StoredCurCodeDecl;
- }
-};
-} // namespace
-
//===----------------------------------------------------------------------===//
// OpenMP Directive Emission
//===----------------------------------------------------------------------===//
+void CodeGenFunction::EmitOMPAggregateAssign(
+ llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen) {
+ // Perform element-by-element initialization.
+ QualType ElementTy;
+ auto SrcBegin = SrcAddr;
+ auto DestBegin = DestAddr;
+ auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
+ auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
+ // Cast from pointer to array type to pointer to single element.
+ SrcBegin = Builder.CreatePointerBitCastOrAddrSpaceCast(SrcBegin,
+ DestBegin->getType());
+ auto DestEnd = Builder.CreateGEP(DestBegin, NumElements);
+ // The basic structure here is a while-do loop.
+ auto BodyBB = createBasicBlock("omp.arraycpy.body");
+ auto DoneBB = createBasicBlock("omp.arraycpy.done");
+ auto IsEmpty =
+ Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
+ Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+
+ // Enter the loop body, making that address the current address.
+ auto EntryBB = Builder.GetInsertBlock();
+ EmitBlock(BodyBB);
+ auto SrcElementCurrent =
+ Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
+ SrcElementCurrent->addIncoming(SrcBegin, EntryBB);
+ auto DestElementCurrent = Builder.CreatePHI(DestBegin->getType(), 2,
+ "omp.arraycpy.destElementPast");
+ DestElementCurrent->addIncoming(DestBegin, EntryBB);
+
+ // Emit copy.
+ CopyGen(DestElementCurrent, SrcElementCurrent);
+
+ // Shift the address forward by one element.
+ auto DestElementNext = Builder.CreateConstGEP1_32(
+ DestElementCurrent, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ auto SrcElementNext = Builder.CreateConstGEP1_32(
+ SrcElementCurrent, /*Idx0=*/1, "omp.arraycpy.src.element");
+ // Check whether we've reached the end.
+ auto Done =
+ Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
+ Builder.CreateCondBr(Done, DoneBB, BodyBB);
+ DestElementCurrent->addIncoming(DestElementNext, Builder.GetInsertBlock());
+ SrcElementCurrent->addIncoming(SrcElementNext, Builder.GetInsertBlock());
+
+ // Done.
+ EmitBlock(DoneBB, /*IsFinished=*/true);
+}
-/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
-/// function. Here is the logic:
-/// if (Cond) {
-/// CodeGen(true);
-/// } else {
-/// CodeGen(false);
-/// }
-static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
- const std::function<void(bool)> &CodeGen) {
- CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
-
- // If the condition constant folds and can be elided, try to avoid emitting
- // the condition and the dead arm of the if/else.
- bool CondConstant;
- if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
- CodeGen(CondConstant);
- return;
- }
-
- // Otherwise, the condition did not fold, or we couldn't elide it. Just
- // emit the conditional branch.
- auto ThenBlock = CGF.createBasicBlock(/*name*/ "omp_if.then");
- auto ElseBlock = CGF.createBasicBlock(/*name*/ "omp_if.else");
- auto ContBlock = CGF.createBasicBlock(/*name*/ "omp_if.end");
- CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount*/ 0);
-
- // Emit the 'then' code.
- CGF.EmitBlock(ThenBlock);
- CodeGen(/*ThenBlock*/ true);
- CGF.EmitBranch(ContBlock);
- // Emit the 'else' code if present.
- {
- // There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
- CGF.EmitBlock(ElseBlock);
- }
- CodeGen(/*ThenBlock*/ false);
- {
- // There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
- CGF.EmitBranch(ContBlock);
- }
- // Emit the continuation block for code after the if.
- CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
-}
-
-void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
- llvm::Value *PrivateAddr,
- const Expr *AssignExpr,
- QualType OriginalType,
- const VarDecl *VDInit) {
- EmitBlock(createBasicBlock(".omp.assign.begin."));
- if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
- // Perform simple memcpy.
- EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
- AssignExpr->getType());
- } else {
- // Perform element-by-element initialization.
- QualType ElementTy;
- auto SrcBegin = OriginalAddr.getAddress();
- auto DestBegin = PrivateAddr;
- auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
- auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
- auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
- auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
- auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
- // The basic structure here is a do-while loop, because we don't
- // need to check for the zero-element case.
- auto BodyBB = createBasicBlock("omp.arraycpy.body");
- auto DoneBB = createBasicBlock("omp.arraycpy.done");
- auto IsEmpty =
- Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
- Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
-
- // Enter the loop body, making that address the current address.
- auto EntryBB = Builder.GetInsertBlock();
- EmitBlock(BodyBB);
- auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
- "omp.arraycpy.srcElementPast");
- SrcElementPast->addIncoming(SrcEnd, EntryBB);
- auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
- "omp.arraycpy.destElementPast");
- DestElementPast->addIncoming(DestEnd, EntryBB);
-
- // Shift the address back by one element.
- auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
- auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
- "omp.arraycpy.dest.element");
- auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
- "omp.arraycpy.src.element");
- {
- // Create RunCleanScope to cleanup possible temps.
- CodeGenFunction::RunCleanupsScope Init(*this);
- // Emit initialization for single element.
- LocalDeclMap[VDInit] = SrcElement;
- EmitAnyExprToMem(AssignExpr, DestElement,
- AssignExpr->getType().getQualifiers(),
- /*IsInitializer*/ false);
- LocalDeclMap.erase(VDInit);
+void CodeGenFunction::EmitOMPCopy(CodeGenFunction &CGF,
+ QualType OriginalType, llvm::Value *DestAddr,
+ llvm::Value *SrcAddr, const VarDecl *DestVD,
+ const VarDecl *SrcVD, const Expr *Copy) {
+ if (OriginalType->isArrayType()) {
+ auto *BO = dyn_cast<BinaryOperator>(Copy);
+ if (BO && BO->getOpcode() == BO_Assign) {
+ // Perform simple memcpy for simple copying.
+ CGF.EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
+ } else {
+ // For arrays with complex element types perform element by element
+ // copying.
+ CGF.EmitOMPAggregateAssign(
+ DestAddr, SrcAddr, OriginalType,
+ [&CGF, Copy, SrcVD, DestVD](llvm::Value *DestElement,
+ llvm::Value *SrcElement) {
+ // Working with the single array element, so have to remap
+ // destination and source variables to corresponding array
+ // elements.
+ CodeGenFunction::OMPPrivateScope Remap(CGF);
+ Remap.addPrivate(DestVD, [DestElement]() -> llvm::Value *{
+ return DestElement;
+ });
+ Remap.addPrivate(
+ SrcVD, [SrcElement]() -> llvm::Value *{ return SrcElement; });
+ (void)Remap.Privatize();
+ CGF.EmitIgnoredExpr(Copy);
+ });
}
-
- // Check whether we've reached the end.
- auto Done =
- Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
- Builder.CreateCondBr(Done, DoneBB, BodyBB);
- DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
- SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
-
- // Done.
- EmitBlock(DoneBB, true);
+ } else {
+ // Remap pseudo source variable to private copy.
+ CodeGenFunction::OMPPrivateScope Remap(CGF);
+ Remap.addPrivate(SrcVD, [SrcAddr]() -> llvm::Value *{ return SrcAddr; });
+ Remap.addPrivate(DestVD, [DestAddr]() -> llvm::Value *{ return DestAddr; });
+ (void)Remap.Privatize();
+ // Emit copying of the whole variable.
+ CGF.EmitIgnoredExpr(Copy);
}
- EmitBlock(createBasicBlock(".omp.assign.end."));
}
-void CodeGenFunction::EmitOMPFirstprivateClause(
- const OMPExecutableDirective &D,
- CodeGenFunction::OMPPrivateScope &PrivateScope) {
- auto PrivateFilter = [](const OMPClause *C) -> bool {
- return C->getClauseKind() == OMPC_firstprivate;
- };
- for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
- I(D.clauses(), PrivateFilter); I; ++I) {
+bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope) {
+ llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
+ for (auto &&I = D.getClausesOfKind(OMPC_firstprivate); I; ++I) {
auto *C = cast<OMPFirstprivateClause>(*I);
auto IRef = C->varlist_begin();
auto InitsRef = C->inits().begin();
for (auto IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- bool IsRegistered;
- if (*InitsRef != nullptr) {
- // Emit VarDecl with copy init for arrays.
- auto *FD = CapturedStmtInfo->lookup(OrigVD);
- LValue Base = MakeNaturalAlignAddrLValue(
- CapturedStmtInfo->getContextValue(),
- getContext().getTagDeclType(FD->getParent()));
- auto OriginalAddr = EmitLValueForField(Base, FD);
- auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
- auto Emission = EmitAutoVarAlloca(*VD);
- // Emit initialization of aggregate firstprivate vars.
- EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
- VD->getInit(), (*IRef)->getType(), VDInit);
- EmitAutoVarCleanups(Emission);
- return Emission.getAllocatedAddress();
- });
- } else
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
- // Emit private VarDecl with copy init.
- EmitDecl(*VD);
- return GetAddrOfLocalVar(VD);
- });
- assert(IsRegistered && "counter already registered as private");
- // Silence the warning about unused variable.
- (void)IsRegistered;
+ if (EmittedAsFirstprivate.count(OrigVD) == 0) {
+ EmittedAsFirstprivate.insert(OrigVD);
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
+ bool IsRegistered;
+ DeclRefExpr DRE(
+ const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
+ OrigVD) != nullptr,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
+ auto *OriginalAddr = EmitLValue(&DRE).getAddress();
+ QualType Type = OrigVD->getType();
+ if (Type->isArrayType()) {
+ // Emit VarDecl with copy init for arrays.
+ // Get the address of the original variable captured in current
+ // captured region.
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ auto Emission = EmitAutoVarAlloca(*VD);
+ auto *Init = VD->getInit();
+ if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
+ Type);
+ } else {
+ EmitOMPAggregateAssign(
+ Emission.getAllocatedAddress(), OriginalAddr, Type,
+ [this, VDInit, Init](llvm::Value *DestElement,
+ llvm::Value *SrcElement) {
+ // Clean up any temporaries needed by the initialization.
+ RunCleanupsScope InitScope(*this);
+ // Emit initialization for single element.
+ LocalDeclMap[VDInit] = SrcElement;
+ EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer*/ false);
+ LocalDeclMap.erase(VDInit);
+ });
+ }
+ EmitAutoVarCleanups(Emission);
+ return Emission.getAllocatedAddress();
+ });
+ } else {
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ // Emit private VarDecl with copy init.
+ // Remap temp VDInit variable to the address of the original
+ // variable
+ // (for proper handling of captured global variables).
+ LocalDeclMap[VDInit] = OriginalAddr;
+ EmitDecl(*VD);
+ LocalDeclMap.erase(VDInit);
+ return GetAddrOfLocalVar(VD);
+ });
+ }
+ assert(IsRegistered &&
+ "firstprivate var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ }
++IRef, ++InitsRef;
}
}
+ return !EmittedAsFirstprivate.empty();
}
void CodeGenFunction::EmitOMPPrivateClause(
const OMPExecutableDirective &D,
CodeGenFunction::OMPPrivateScope &PrivateScope) {
- auto PrivateFilter = [](const OMPClause *C) -> bool {
- return C->getClauseKind() == OMPC_private;
- };
- for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
- I(D.clauses(), PrivateFilter); I; ++I) {
+ llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
+ for (auto &&I = D.getClausesOfKind(OMPC_private); I; ++I) {
auto *C = cast<OMPPrivateClause>(*I);
auto IRef = C->varlist_begin();
for (auto IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
+ auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ bool IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ // Emit private VarDecl with copy init.
+ EmitDecl(*VD);
+ return GetAddrOfLocalVar(VD);
+ });
+ assert(IsRegistered && "private var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ }
+ ++IRef;
+ }
+ }
+}
+
+bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
+ // threadprivate_var1 = master_threadprivate_var1;
+ // operator=(threadprivate_var2, master_threadprivate_var2);
+ // ...
+ // __kmpc_barrier(&loc, global_tid);
+ llvm::DenseSet<const VarDecl *> CopiedVars;
+ llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
+ for (auto &&I = D.getClausesOfKind(OMPC_copyin); I; ++I) {
+ auto *C = cast<OMPCopyinClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto ISrcRef = C->source_exprs().begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *AssignOp : C->assignment_ops()) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ QualType Type = VD->getType();
+ if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
+ // Get the address of the master variable.
+ auto *MasterAddr = VD->isStaticLocal()
+ ? CGM.getStaticLocalDeclAddress(VD)
+ : CGM.GetAddrOfGlobal(VD);
+ // Get the address of the threadprivate variable.
+ auto *PrivateAddr = EmitLValue(*IRef).getAddress();
+ if (CopiedVars.size() == 1) {
+ // At first check if current thread is a master thread. If it is, no
+ // need to copy data.
+ CopyBegin = createBasicBlock("copyin.not.master");
+ CopyEnd = createBasicBlock("copyin.not.master.end");
+ Builder.CreateCondBr(
+ Builder.CreateICmpNE(
+ Builder.CreatePtrToInt(MasterAddr, CGM.IntPtrTy),
+ Builder.CreatePtrToInt(PrivateAddr, CGM.IntPtrTy)),
+ CopyBegin, CopyEnd);
+ EmitBlock(CopyBegin);
+ }
+ auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ EmitOMPCopy(*this, Type, PrivateAddr, MasterAddr, DestVD, SrcVD,
+ AssignOp);
+ }
+ ++IRef;
+ ++ISrcRef;
+ ++IDestRef;
+ }
+ }
+ if (CopyEnd) {
+ // Exit out of copying procedure for non-master thread.
+ EmitBlock(CopyEnd, /*IsFinished=*/true);
+ return true;
+ }
+ return false;
+}
+
+bool CodeGenFunction::EmitOMPLastprivateClauseInit(
+ const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
+ bool HasAtLeastOneLastprivate = false;
+ llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
+ for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {
+ HasAtLeastOneLastprivate = true;
+ auto *C = cast<OMPLastprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *IInit : C->private_copies()) {
+ // Keep the address of the original variable for future update at the end
+ // of the loop.
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> llvm::Value *{
+ DeclRefExpr DRE(
+ const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
+ OrigVD) != nullptr,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
+ return EmitLValue(&DRE).getAddress();
+ });
+ // Check if the variable is also a firstprivate: in this case IInit is
+ // not generated. Initialization of this variable will happen in codegen
+ // for 'firstprivate' clause.
+ if (IInit) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ bool IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ // Emit private VarDecl with copy init.
+ EmitDecl(*VD);
+ return GetAddrOfLocalVar(VD);
+ });
+ assert(IsRegistered &&
+ "lastprivate var already registered as private");
+ (void)IsRegistered;
+ }
+ }
+ ++IRef, ++IDestRef;
+ }
+ }
+ return HasAtLeastOneLastprivate;
+}
+
+void CodeGenFunction::EmitOMPLastprivateClauseFinal(
+ const OMPExecutableDirective &D, llvm::Value *IsLastIterCond) {
+ // Emit following code:
+ // if (<IsLastIterCond>) {
+ // orig_var1 = private_orig_var1;
+ // ...
+ // orig_varn = private_orig_varn;
+ // }
+ llvm::BasicBlock *ThenBB = nullptr;
+ llvm::BasicBlock *DoneBB = nullptr;
+ if (IsLastIterCond) {
+ ThenBB = createBasicBlock(".omp.lastprivate.then");
+ DoneBB = createBasicBlock(".omp.lastprivate.done");
+ Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
+ EmitBlock(ThenBB);
+ }
+ llvm::DenseMap<const Decl *, const Expr *> LoopCountersAndUpdates;
+ const Expr *LastIterVal = nullptr;
+ const Expr *IVExpr = nullptr;
+ const Expr *IncExpr = nullptr;
+ if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
+ if (isOpenMPWorksharingDirective(D.getDirectiveKind())) {
+ LastIterVal = cast<VarDecl>(cast<DeclRefExpr>(
+ LoopDirective->getUpperBoundVariable())
+ ->getDecl())
+ ->getAnyInitializer();
+ IVExpr = LoopDirective->getIterationVariable();
+ IncExpr = LoopDirective->getInc();
+ auto IUpdate = LoopDirective->updates().begin();
+ for (auto *E : LoopDirective->counters()) {
+ auto *D = cast<DeclRefExpr>(E)->getDecl()->getCanonicalDecl();
+ LoopCountersAndUpdates[D] = *IUpdate;
+ ++IUpdate;
+ }
+ }
+ }
+ {
+ llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
+ bool FirstLCV = true;
+ for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {
+ auto *C = cast<OMPLastprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto ISrcRef = C->source_exprs().begin();
+ auto IDestRef = C->destination_exprs().begin();
+ for (auto *AssignOp : C->assignment_ops()) {
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ QualType Type = PrivateVD->getType();
+ auto *CanonicalVD = PrivateVD->getCanonicalDecl();
+ if (AlreadyEmittedVars.insert(CanonicalVD).second) {
+ // If lastprivate variable is a loop control variable for loop-based
+ // directive, update its value before copyin back to original
+ // variable.
+ if (auto *UpExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) {
+ if (FirstLCV && LastIterVal) {
+ EmitAnyExprToMem(LastIterVal, EmitLValue(IVExpr).getAddress(),
+ IVExpr->getType().getQualifiers(),
+ /*IsInitializer=*/false);
+ EmitIgnoredExpr(IncExpr);
+ FirstLCV = false;
+ }
+ EmitIgnoredExpr(UpExpr);
+ }
+ auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
+ auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
+ // Get the address of the original variable.
+ auto *OriginalAddr = GetAddrOfLocalVar(DestVD);
+ // Get the address of the private variable.
+ auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD);
+ EmitOMPCopy(*this, Type, OriginalAddr, PrivateAddr, DestVD, SrcVD,
+ AssignOp);
+ }
+ ++IRef;
+ ++ISrcRef;
+ ++IDestRef;
+ }
+ }
+ }
+ if (IsLastIterCond) {
+ EmitBlock(DoneBB, /*IsFinished=*/true);
+ }
+}
+
+void CodeGenFunction::EmitOMPReductionClauseInit(
+ const OMPExecutableDirective &D,
+ CodeGenFunction::OMPPrivateScope &PrivateScope) {
+ for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {
+ auto *C = cast<OMPReductionClause>(*I);
+ auto ILHS = C->lhs_exprs().begin();
+ auto IRHS = C->rhs_exprs().begin();
+ for (auto IRef : C->varlists()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
+ auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ // Store the address of the original variable associated with the LHS
+ // implicit variable.
+ PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef]() -> llvm::Value *{
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ IRef->getType(), VK_LValue, IRef->getExprLoc());
+ return EmitLValue(&DRE).getAddress();
+ });
+ // Emit reduction copy.
bool IsRegistered =
- PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
- // Emit private VarDecl with copy init.
- EmitDecl(*VD);
- return GetAddrOfLocalVar(VD);
+ PrivateScope.addPrivate(OrigVD, [this, PrivateVD]() -> llvm::Value *{
+ // Emit private VarDecl with reduction init.
+ EmitDecl(*PrivateVD);
+ return GetAddrOfLocalVar(PrivateVD);
});
- assert(IsRegistered && "counter already registered as private");
+ assert(IsRegistered && "private var already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
- ++IRef;
+ ++ILHS, ++IRHS;
}
}
}
-/// \brief Emits code for OpenMP parallel directive in the parallel region.
-static void EmitOMPParallelCall(CodeGenFunction &CGF,
- const OMPParallelDirective &S,
- llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct) {
- if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
+void CodeGenFunction::EmitOMPReductionClauseFinal(
+ const OMPExecutableDirective &D) {
+ llvm::SmallVector<const Expr *, 8> LHSExprs;
+ llvm::SmallVector<const Expr *, 8> RHSExprs;
+ llvm::SmallVector<const Expr *, 8> ReductionOps;
+ bool HasAtLeastOneReduction = false;
+ for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {
+ HasAtLeastOneReduction = true;
+ auto *C = cast<OMPReductionClause>(*I);
+ LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
+ RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
+ ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
+ }
+ if (HasAtLeastOneReduction) {
+ // Emit nowait reduction if nowait clause is present or directive is a
+ // parallel directive (it always has implicit barrier).
+ CGM.getOpenMPRuntime().emitReduction(
+ *this, D.getLocEnd(), LHSExprs, RHSExprs, ReductionOps,
+ D.getSingleClause(OMPC_nowait) ||
+ isOpenMPParallelDirective(D.getDirectiveKind()) ||
+ D.getDirectiveKind() == OMPD_simd,
+ D.getDirectiveKind() == OMPD_simd);
+ }
+}
+
+static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen) {
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS);
+ auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
+ S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
+ if (auto C = S.getSingleClause(OMPC_num_threads)) {
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
/*IgnoreResultAssign*/ true);
- CGF.CGM.getOpenMPRuntime().EmitOMPNumThreadsClause(
+ CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
CGF, NumThreads, NumThreadsClause->getLocStart());
}
- CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
- OutlinedFn, CapturedStruct);
+ if (auto *C = S.getSingleClause(OMPC_proc_bind)) {
+ CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
+ auto *ProcBindClause = cast<OMPProcBindClause>(C);
+ CGF.CGM.getOpenMPRuntime().emitProcBindClause(
+ CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart());
+ }
+ const Expr *IfCond = nullptr;
+ if (auto C = S.getSingleClause(OMPC_if)) {
+ IfCond = cast<OMPIfClause>(C)->getCondition();
+ }
+ CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn,
+ CapturedStruct, IfCond);
}
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
- auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
- auto OutlinedFn = CGM.getOpenMPRuntime().EmitOpenMPOutlinedFunction(
- S, *CS->getCapturedDecl()->param_begin());
- if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
- auto Cond = cast<OMPIfClause>(C)->getCondition();
- EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
- if (ThenBlock)
- EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
- else
- CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
- OutlinedFn, CapturedStruct);
- });
- } else
- EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
+ LexicalScope Scope(*this, S.getSourceRange());
+ // Emit parallel region as a standalone region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ OMPPrivateScope PrivateScope(CGF);
+ bool Copyins = CGF.EmitOMPCopyinClause(S);
+ bool Firstprivates = CGF.EmitOMPFirstprivateClause(S, PrivateScope);
+ if (Copyins || Firstprivates) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables or propagation master's thread
+ // values of threadprivate variables to local instances of that variables
+ // of all other implicit threads.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_unknown);
+ }
+ CGF.EmitOMPPrivateClause(S, PrivateScope);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EmitOMPReductionClauseFinal(S);
+ // Emit implicit barrier at the end of the 'parallel' directive.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_unknown);
+ };
+ emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen);
}
-void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
- bool SeparateIter) {
+void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
+ JumpDest LoopExit) {
RunCleanupsScope BodyScope(*this);
// Update counters values on current iteration.
- for (auto I : S.updates()) {
+ for (auto I : D.updates()) {
EmitIgnoredExpr(I);
}
+ // Update the linear variables.
+ for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
+ auto *C = cast<OMPLinearClause>(*I);
+ for (auto U : C->updates()) {
+ EmitIgnoredExpr(U);
+ }
+ }
+
// On a continue in the body, jump to the end.
auto Continue = getJumpDestInCurrentScope("omp.body.continue");
- BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
// Emit loop body.
- EmitStmt(S.getBody());
+ EmitStmt(D.getBody());
// The end (updates/cleanups).
EmitBlock(Continue.getBlock());
BreakContinueStack.pop_back();
- if (SeparateIter) {
// TODO: Update lastprivates if the SeparateIter flag is true.
// This will be implemented in a follow-up OMPLastprivateClause patch, but
// result should be still correct without it, as we do not make these
// variables private yet.
- }
}
-void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
- OMPPrivateScope &LoopScope,
- bool SeparateIter) {
+void CodeGenFunction::EmitOMPInnerLoop(
+ const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
+ const Expr *IncExpr,
+ const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
+ const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen) {
auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
- auto Cnt = getPGORegionCounter(&S);
// Start the loop with a block that tests the condition.
auto CondBlock = createBasicBlock("omp.inner.for.cond");
@@ -311,35 +550,31 @@ void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
auto ExitBlock = LoopExit.getBlock();
- if (LoopScope.requiresCleanups())
+ if (RequiresCleanup)
ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
auto LoopBody = createBasicBlock("omp.inner.for.body");
- // Emit condition: "IV < LastIteration + 1 [ - 1]"
- // ("- 1" when lastprivate clause is present - separate one iteration).
- llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond(SeparateIter));
- Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(SeparateIter), Cnt));
-
+ // Emit condition.
+ EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
EmitBlock(LoopBody);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(&S);
// Create a block for the increment.
auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
- EmitOMPLoopBody(S);
- EmitStopPoint(&S);
+ BodyGen(*this);
// Emit "IV = IV + 1" and a back-edge to the condition block.
EmitBlock(Continue.getBlock());
- EmitIgnoredExpr(S.getInc());
+ EmitIgnoredExpr(IncExpr);
+ PostIncGen(*this);
BreakContinueStack.pop_back();
EmitBranch(CondBlock);
LoopStack.pop();
@@ -347,157 +582,433 @@ void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
EmitBlock(LoopExit.getBlock());
}
-void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) {
- auto IC = S.counters().begin();
- for (auto F : S.finals()) {
- if (LocalDeclMap.lookup(cast<DeclRefExpr>((*IC))->getDecl())) {
- EmitIgnoredExpr(F);
+void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
+ // Emit inits for the linear variables.
+ for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
+ auto *C = cast<OMPLinearClause>(*I);
+ for (auto Init : C->inits()) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
+ auto *OrigVD = cast<VarDecl>(
+ cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())->getDecl());
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ VD->getInit()->getType(), VK_LValue,
+ VD->getInit()->getExprLoc());
+ AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
+ EmitExprAsInit(&DRE, VD,
+ MakeAddrLValue(Emission.getAllocatedAddress(),
+ VD->getType(), Emission.Alignment),
+ /*capturedByInit=*/false);
+ EmitAutoVarCleanups(Emission);
}
- ++IC;
+ // Emit the linear steps for the linear clauses.
+ // If a step is not constant, it is pre-calculated before the loop.
+ if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
+ if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
+ EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
+ // Emit calculation of the linear step.
+ EmitIgnoredExpr(CS);
+ }
}
}
-static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
- const OMPAlignedClause &Clause) {
- unsigned ClauseAlignment = 0;
- if (auto AlignmentExpr = Clause.getAlignment()) {
- auto AlignmentCI =
- cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
- ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
+static void emitLinearClauseFinal(CodeGenFunction &CGF,
+ const OMPLoopDirective &D) {
+ // Emit the final values of the linear variables.
+ for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
+ auto *C = cast<OMPLinearClause>(*I);
+ auto IC = C->varlist_begin();
+ for (auto F : C->finals()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
+ auto *OrigAddr = CGF.EmitLValue(&DRE).getAddress();
+ CodeGenFunction::OMPPrivateScope VarScope(CGF);
+ VarScope.addPrivate(OrigVD,
+ [OrigAddr]() -> llvm::Value *{ return OrigAddr; });
+ (void)VarScope.Privatize();
+ CGF.EmitIgnoredExpr(F);
+ ++IC;
+ }
}
- for (auto E : Clause.varlists()) {
- unsigned Alignment = ClauseAlignment;
- if (Alignment == 0) {
- // OpenMP [2.8.1, Description]
- // If no optional parameter is specified, implementation-defined default
- // alignments for SIMD instructions on the target platforms are assumed.
- Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
- E->getType());
+}
+
+static void emitAlignedClause(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D) {
+ for (auto &&I = D.getClausesOfKind(OMPC_aligned); I; ++I) {
+ auto *Clause = cast<OMPAlignedClause>(*I);
+ unsigned ClauseAlignment = 0;
+ if (auto AlignmentExpr = Clause->getAlignment()) {
+ auto AlignmentCI =
+ cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
+ ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
}
- assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
- "alignment is not power of 2");
- if (Alignment != 0) {
- llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
- CGF.EmitAlignmentAssumption(PtrValue, Alignment);
+ for (auto E : Clause->varlists()) {
+ unsigned Alignment = ClauseAlignment;
+ if (Alignment == 0) {
+ // OpenMP [2.8.1, Description]
+ // If no optional parameter is specified, implementation-defined default
+ // alignments for SIMD instructions on the target platforms are assumed.
+ Alignment =
+ CGF.getContext()
+ .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
+ E->getType()->getPointeeType()))
+ .getQuantity();
+ }
+ assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
+ "alignment is not power of 2");
+ if (Alignment != 0) {
+ llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
+ CGF.EmitAlignmentAssumption(PtrValue, Alignment);
+ }
}
}
}
-static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
+static void emitPrivateLoopCounters(CodeGenFunction &CGF,
CodeGenFunction::OMPPrivateScope &LoopScope,
ArrayRef<Expr *> Counters) {
for (auto *E : Counters) {
auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
+ (void)LoopScope.addPrivate(VD, [&]() -> llvm::Value *{
// Emit var without initialization.
auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
CGF.EmitAutoVarCleanups(VarEmission);
return VarEmission.getAllocatedAddress();
});
+ }
+}
+
+static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
+ const Expr *Cond, llvm::BasicBlock *TrueBlock,
+ llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
+ {
+ CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
+ emitPrivateLoopCounters(CGF, PreCondScope, S.counters());
+ const VarDecl *IVDecl =
+ cast<VarDecl>(cast<DeclRefExpr>(S.getIterationVariable())->getDecl());
+ bool IsRegistered = PreCondScope.addPrivate(IVDecl, [&]() -> llvm::Value *{
+ // Emit var without initialization.
+ auto VarEmission = CGF.EmitAutoVarAlloca(*IVDecl);
+ CGF.EmitAutoVarCleanups(VarEmission);
+ return VarEmission.getAllocatedAddress();
+ });
assert(IsRegistered && "counter already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
+ (void)PreCondScope.Privatize();
+ // Initialize internal counter to 0 to calculate initial values of real
+ // counters.
+ LValue IV = CGF.EmitLValue(S.getIterationVariable());
+ CGF.EmitStoreOfScalar(
+ llvm::ConstantInt::getNullValue(
+ IV.getAddress()->getType()->getPointerElementType()),
+ CGF.EmitLValue(S.getIterationVariable()), /*isInit=*/true);
+ // Get initial values of real counters.
+ for (auto I : S.updates()) {
+ CGF.EmitIgnoredExpr(I);
+ }
}
- (void)LoopScope.Privatize();
+ // Check that loop is executed at least one time.
+ CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
}
-void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
- // Pragma 'simd' code depends on presence of 'lastprivate'.
- // If present, we have to separate last iteration of the loop:
- //
- // if (LastIteration != 0) {
- // for (IV in 0..LastIteration-1) BODY;
- // BODY with updates of lastprivate vars;
- // <Final counter/linear vars updates>;
- // }
- //
- // otherwise (when there's no lastprivate):
- //
- // for (IV in 0..LastIteration) BODY;
- // <Final counter/linear vars updates>;
- //
+static void
+emitPrivateLinearVars(CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ CodeGenFunction::OMPPrivateScope &PrivateScope) {
+ for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
+ auto *C = cast<OMPLinearClause>(*I);
+ for (auto *E : C->varlists()) {
+ auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ bool IsRegistered = PrivateScope.addPrivate(VD, [&]()->llvm::Value * {
+ // Emit var without initialization.
+ auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
+ CGF.EmitAutoVarCleanups(VarEmission);
+ return VarEmission.getAllocatedAddress();
+ });
+ assert(IsRegistered && "linear var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ }
+ }
+}
+static void emitSafelenClause(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D) {
+ if (auto *C =
+ cast_or_null<OMPSafelenClause>(D.getSingleClause(OMPC_safelen))) {
+ RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
+ /*ignoreResult=*/true);
+ llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
+ CGF.LoopStack.setVectorizerWidth(Val->getZExtValue());
+ // In presence of finite 'safelen', it may be unsafe to mark all
+ // the memory instructions parallel, because loop-carried
+ // dependences of 'safelen' iterations are possible.
+ CGF.LoopStack.setParallel(false);
+ }
+}
+
+void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D) {
// Walk clauses and process safelen/lastprivate.
- bool SeparateIter = false;
LoopStack.setParallel();
LoopStack.setVectorizerEnable(true);
- for (auto C : S.clauses()) {
- switch (C->getClauseKind()) {
- case OMPC_safelen: {
- RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
- AggValueSlot::ignored(), true);
- llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
- LoopStack.setVectorizerWidth(Val->getZExtValue());
- // In presence of finite 'safelen', it may be unsafe to mark all
- // the memory instructions parallel, because loop-carried
- // dependences of 'safelen' iterations are possible.
- LoopStack.setParallel(false);
- break;
- }
- case OMPC_aligned:
- EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
- break;
- case OMPC_lastprivate:
- SeparateIter = true;
- break;
- default:
- // Not handled yet
- ;
+ emitSafelenClause(*this, D);
+}
+
+void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &D) {
+ auto IC = D.counters().begin();
+ for (auto F : D.finals()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
+ if (LocalDeclMap.lookup(OrigVD) || CapturedStmtInfo->lookup(OrigVD)) {
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
+ auto *OrigAddr = EmitLValue(&DRE).getAddress();
+ OMPPrivateScope VarScope(*this);
+ VarScope.addPrivate(OrigVD,
+ [OrigAddr]() -> llvm::Value *{ return OrigAddr; });
+ (void)VarScope.Privatize();
+ EmitIgnoredExpr(F);
}
+ ++IC;
}
+ emitLinearClauseFinal(*this, D);
+}
- InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
- RunCleanupsScope DirectiveScope(*this);
+void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ // if (PreCond) {
+ // for (IV in 0..LastIteration) BODY;
+ // <Final counter/linear vars updates>;
+ // }
+ //
+
+ // Emit: if (PreCond) - begin.
+ // If the condition constant folds and can be elided, avoid emitting the
+ // whole loop.
+ bool CondConstant;
+ llvm::BasicBlock *ContBlock = nullptr;
+ if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
+ if (!CondConstant)
+ return;
+ } else {
+ auto *ThenBlock = CGF.createBasicBlock("simd.if.then");
+ ContBlock = CGF.createBasicBlock("simd.if.end");
+ emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
+ CGF.getProfileCount(&S));
+ CGF.EmitBlock(ThenBlock);
+ CGF.incrementProfileCounter(&S);
+ }
- CGDebugInfo *DI = getDebugInfo();
- if (DI)
- DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
+ // Emit the loop iteration variable.
+ const Expr *IVExpr = S.getIterationVariable();
+ const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
+ CGF.EmitVarDecl(*IVDecl);
+ CGF.EmitIgnoredExpr(S.getInit());
+
+ // Emit the iterations count variable.
+ // If it is not a variable, Sema decided to calculate iterations count on
+ // each iteration (e.g., it is foldable into a constant).
+ if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
+ CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
+ // Emit calculation of the iterations count.
+ CGF.EmitIgnoredExpr(S.getCalcLastIteration());
+ }
+
+ CGF.EmitOMPSimdInit(S);
+
+ emitAlignedClause(CGF, S);
+ CGF.EmitOMPLinearClauseInit(S);
+ bool HasLastprivateClause;
+ {
+ OMPPrivateScope LoopScope(CGF);
+ emitPrivateLoopCounters(CGF, LoopScope, S.counters());
+ emitPrivateLinearVars(CGF, S, LoopScope);
+ CGF.EmitOMPPrivateClause(S, LoopScope);
+ CGF.EmitOMPReductionClauseInit(S, LoopScope);
+ HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
+ (void)LoopScope.Privatize();
+ CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
+ S.getInc(),
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, JumpDest());
+ CGF.EmitStopPoint(&S);
+ },
+ [](CodeGenFunction &) {});
+ // Emit final copy of the lastprivate variables at the end of loops.
+ if (HasLastprivateClause) {
+ CGF.EmitOMPLastprivateClauseFinal(S);
+ }
+ CGF.EmitOMPReductionClauseFinal(S);
+ }
+ CGF.EmitOMPSimdFinal(S);
+ // Emit: if (PreCond) - end.
+ if (ContBlock) {
+ CGF.EmitBranch(ContBlock);
+ CGF.EmitBlock(ContBlock, true);
+ }
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
+}
+
+void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
+ const OMPLoopDirective &S,
+ OMPPrivateScope &LoopScope,
+ bool Ordered, llvm::Value *LB,
+ llvm::Value *UB, llvm::Value *ST,
+ llvm::Value *IL, llvm::Value *Chunk) {
+ auto &RT = CGM.getOpenMPRuntime();
+
+ // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
+ const bool DynamicOrOrdered = Ordered || RT.isDynamic(ScheduleKind);
+
+ assert((Ordered ||
+ !RT.isStaticNonchunked(ScheduleKind, /*Chunked=*/Chunk != nullptr)) &&
+ "static non-chunked schedule does not need outer loop");
+
+ // Emit outer loop.
+ //
+ // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
+ // When schedule(dynamic,chunk_size) is specified, the iterations are
+ // distributed to threads in the team in chunks as the threads request them.
+ // Each thread executes a chunk of iterations, then requests another chunk,
+ // until no chunks remain to be distributed. Each chunk contains chunk_size
+ // iterations, except for the last chunk to be distributed, which may have
+ // fewer iterations. When no chunk_size is specified, it defaults to 1.
+ //
+ // When schedule(guided,chunk_size) is specified, the iterations are assigned
+ // to threads in the team in chunks as the executing threads request them.
+ // Each thread executes a chunk of iterations, then requests another chunk,
+ // until no chunks remain to be assigned. For a chunk_size of 1, the size of
+ // each chunk is proportional to the number of unassigned iterations divided
+ // by the number of threads in the team, decreasing to 1. For a chunk_size
+ // with value k (greater than 1), the size of each chunk is determined in the
+ // same way, with the restriction that the chunks do not contain fewer than k
+ // iterations (except for the last chunk to be assigned, which may have fewer
+ // than k iterations).
+ //
+ // When schedule(auto) is specified, the decision regarding scheduling is
+ // delegated to the compiler and/or runtime system. The programmer gives the
+ // implementation the freedom to choose any possible mapping of iterations to
+ // threads in the team.
+ //
+ // When schedule(runtime) is specified, the decision regarding scheduling is
+ // deferred until run time, and the schedule and chunk size are taken from the
+ // run-sched-var ICV. If the ICV is set to auto, the schedule is
+ // implementation defined
+ //
+ // while(__kmpc_dispatch_next(&LB, &UB)) {
+ // idx = LB;
+ // while (idx <= UB) { BODY; ++idx;
+ // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
+ // } // inner loop
+ // }
+ //
+ // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
+ // When schedule(static, chunk_size) is specified, iterations are divided into
+ // chunks of size chunk_size, and the chunks are assigned to the threads in
+ // the team in a round-robin fashion in the order of the thread number.
+ //
+ // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
+ // while (idx <= UB) { BODY; ++idx; } // inner loop
+ // LB = LB + ST;
+ // UB = UB + ST;
+ // }
+ //
- // Emit the loop iteration variable.
const Expr *IVExpr = S.getIterationVariable();
- const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
- EmitVarDecl(*IVDecl);
- EmitIgnoredExpr(S.getInit());
+ const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
+ const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
- // Emit the iterations count variable.
- // If it is not a variable, Sema decided to calculate iterations count on each
- // iteration (e.g., it is foldable into a constant).
- if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
- EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
- // Emit calculation of the iterations count.
- EmitIgnoredExpr(S.getCalcLastIteration());
+ RT.emitForInit(
+ *this, S.getLocStart(), ScheduleKind, IVSize, IVSigned, Ordered, IL, LB,
+ (DynamicOrOrdered ? EmitAnyExpr(S.getLastIteration()).getScalarVal()
+ : UB),
+ ST, Chunk);
+
+ auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
+
+ // Start the loop with a block that tests the condition.
+ auto CondBlock = createBasicBlock("omp.dispatch.cond");
+ EmitBlock(CondBlock);
+ LoopStack.push(CondBlock);
+
+ llvm::Value *BoolCondVal = nullptr;
+ if (!DynamicOrOrdered) {
+ // UB = min(UB, GlobalUB)
+ EmitIgnoredExpr(S.getEnsureUpperBound());
+ // IV = LB
+ EmitIgnoredExpr(S.getInit());
+ // IV < UB
+ BoolCondVal = EvaluateExprAsBool(S.getCond());
+ } else {
+ BoolCondVal = RT.emitForNext(*this, S.getLocStart(), IVSize, IVSigned,
+ IL, LB, UB, ST);
}
- if (SeparateIter) {
- // Emit: if (LastIteration > 0) - begin.
- RegionCounter Cnt = getPGORegionCounter(&S);
- auto ThenBlock = createBasicBlock("simd.if.then");
- auto ContBlock = createBasicBlock("simd.if.end");
- EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
- EmitBlock(ThenBlock);
- Cnt.beginRegion(Builder);
- // Emit 'then' code.
- {
- OMPPrivateScope LoopScope(*this);
- EmitPrivateLoopCounters(*this, LoopScope, S.counters());
- EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
- EmitOMPLoopBody(S, /* SeparateIter */ true);
- }
- EmitOMPSimdFinal(S);
- // Emit: if (LastIteration != 0) - end.
- EmitBranch(ContBlock);
- EmitBlock(ContBlock, true);
+ // If there are any cleanups between here and the loop-exit scope,
+ // create a block to stage a loop exit along.
+ auto ExitBlock = LoopExit.getBlock();
+ if (LoopScope.requiresCleanups())
+ ExitBlock = createBasicBlock("omp.dispatch.cleanup");
+
+ auto LoopBody = createBasicBlock("omp.dispatch.body");
+ Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
+ if (ExitBlock != LoopExit.getBlock()) {
+ EmitBlock(ExitBlock);
+ EmitBranchThroughCleanup(LoopExit);
+ }
+ EmitBlock(LoopBody);
+
+ // Emit "IV = LB" (in case of static schedule, we have already calculated new
+ // LB for loop condition and emitted it above).
+ if (DynamicOrOrdered)
+ EmitIgnoredExpr(S.getInit());
+
+ // Create a block for the increment.
+ auto Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+
+ // Generate !llvm.loop.parallel metadata for loads and stores for loops
+ // with dynamic/guided scheduling and without ordered clause.
+ if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
+ LoopStack.setParallel((ScheduleKind == OMPC_SCHEDULE_dynamic ||
+ ScheduleKind == OMPC_SCHEDULE_guided) &&
+ !Ordered);
} else {
- {
- OMPPrivateScope LoopScope(*this);
- EmitPrivateLoopCounters(*this, LoopScope, S.counters());
- EmitOMPInnerLoop(S, LoopScope);
- }
- EmitOMPSimdFinal(S);
+ EmitOMPSimdInit(S);
}
- if (DI)
- DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
+ SourceLocation Loc = S.getLocStart();
+ EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
+ [&S, LoopExit](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, LoopExit);
+ CGF.EmitStopPoint(&S);
+ },
+ [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) {
+ if (Ordered) {
+ CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(
+ CGF, Loc, IVSize, IVSigned);
+ }
+ });
+
+ EmitBlock(Continue.getBlock());
+ BreakContinueStack.pop_back();
+ if (!DynamicOrOrdered) {
+ // Emit "LB = LB + Stride", "UB = UB + Stride".
+ EmitIgnoredExpr(S.getNextLowerBound());
+ EmitIgnoredExpr(S.getNextUpperBound());
+ }
+
+ EmitBranch(CondBlock);
+ LoopStack.pop();
+ // Emit the fall-through block.
+ EmitBlock(LoopExit.getBlock());
+
+ // Tell the runtime we are done.
+ if (!DynamicOrOrdered)
+ RT.emitForStaticFinish(*this, S.getLocEnd());
}
/// \brief Emit a helper variable and return corresponding lvalue.
@@ -508,7 +1019,39 @@ static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
return CGF.EmitLValue(Helper);
}
-void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
+static std::pair<llvm::Value * /*Chunk*/, OpenMPScheduleClauseKind>
+emitScheduleClause(CodeGenFunction &CGF, const OMPLoopDirective &S,
+ bool OuterRegion) {
+ // Detect the loop schedule kind and chunk.
+ auto ScheduleKind = OMPC_SCHEDULE_unknown;
+ llvm::Value *Chunk = nullptr;
+ if (auto *C =
+ cast_or_null<OMPScheduleClause>(S.getSingleClause(OMPC_schedule))) {
+ ScheduleKind = C->getScheduleKind();
+ if (const auto *Ch = C->getChunkSize()) {
+ if (auto *ImpRef = cast_or_null<DeclRefExpr>(C->getHelperChunkSize())) {
+ if (OuterRegion) {
+ const VarDecl *ImpVar = cast<VarDecl>(ImpRef->getDecl());
+ CGF.EmitVarDecl(*ImpVar);
+ CGF.EmitStoreThroughLValue(
+ CGF.EmitAnyExpr(Ch),
+ CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(ImpVar),
+ ImpVar->getType()));
+ } else {
+ Ch = ImpRef;
+ }
+ }
+ if (!C->getHelperChunkSize() || !OuterRegion) {
+ Chunk = CGF.EmitScalarExpr(Ch);
+ Chunk = CGF.EmitScalarConversion(Chunk, Ch->getType(),
+ S.getIterationVariable()->getType());
+ }
+ }
+ }
+ return std::make_pair(Chunk, ScheduleKind);
+}
+
+bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
// Emit the loop iteration variable.
auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
@@ -525,15 +1068,28 @@ void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
auto &RT = CGM.getOpenMPRuntime();
+ bool HasLastprivateClause;
// Check pre-condition.
{
// Skip the entire loop if we don't meet the precondition.
- RegionCounter Cnt = getPGORegionCounter(&S);
- auto ThenBlock = createBasicBlock("omp.precond.then");
- auto ContBlock = createBasicBlock("omp.precond.end");
- EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
- EmitBlock(ThenBlock);
- Cnt.beginRegion(Builder);
+ // If the condition constant folds and can be elided, avoid emitting the
+ // whole loop.
+ bool CondConstant;
+ llvm::BasicBlock *ContBlock = nullptr;
+ if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
+ if (!CondConstant)
+ return false;
+ } else {
+ auto *ThenBlock = createBasicBlock("omp.precond.then");
+ ContBlock = createBasicBlock("omp.precond.end");
+ emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
+ getProfileCount(&S));
+ EmitBlock(ThenBlock);
+ incrementProfileCounter(&S);
+ }
+
+ emitAlignedClause(*this, S);
+ EmitOMPLinearClauseInit(S);
// Emit 'then' code.
{
// Emit helper vars inits.
@@ -547,152 +1103,994 @@ void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
OMPPrivateScope LoopScope(*this);
- EmitPrivateLoopCounters(*this, LoopScope, S.counters());
+ if (EmitOMPFirstprivateClause(S, LoopScope)) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables.
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_unknown);
+ }
+ EmitOMPPrivateClause(S, LoopScope);
+ HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
+ EmitOMPReductionClauseInit(S, LoopScope);
+ emitPrivateLoopCounters(*this, LoopScope, S.counters());
+ emitPrivateLinearVars(*this, S, LoopScope);
+ (void)LoopScope.Privatize();
// Detect the loop schedule kind and chunk.
- auto ScheduleKind = OMPC_SCHEDULE_unknown;
- llvm::Value *Chunk = nullptr;
- if (auto C = cast_or_null<OMPScheduleClause>(
- S.getSingleClause(OMPC_schedule))) {
- ScheduleKind = C->getScheduleKind();
- if (auto Ch = C->getChunkSize()) {
- Chunk = EmitScalarExpr(Ch);
- Chunk = EmitScalarConversion(Chunk, Ch->getType(),
- S.getIterationVariable()->getType());
- }
- }
+ llvm::Value *Chunk;
+ OpenMPScheduleClauseKind ScheduleKind;
+ auto ScheduleInfo =
+ emitScheduleClause(*this, S, /*OuterRegion=*/false);
+ Chunk = ScheduleInfo.first;
+ ScheduleKind = ScheduleInfo.second;
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
+ const bool Ordered = S.getSingleClause(OMPC_ordered) != nullptr;
if (RT.isStaticNonchunked(ScheduleKind,
- /* Chunked */ Chunk != nullptr)) {
+ /* Chunked */ Chunk != nullptr) &&
+ !Ordered) {
+ if (isOpenMPSimdDirective(S.getDirectiveKind())) {
+ EmitOMPSimdInit(S);
+ }
// OpenMP [2.7.1, Loop Construct, Description, table 2-1]
// When no chunk_size is specified, the iteration space is divided into
// chunks that are approximately equal in size, and at most one chunk is
// distributed to each thread. Note that the size of the chunks is
// unspecified in this case.
- RT.EmitOMPForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
- IL.getAddress(), LB.getAddress(), UB.getAddress(),
- ST.getAddress());
+ RT.emitForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
+ Ordered, IL.getAddress(), LB.getAddress(),
+ UB.getAddress(), ST.getAddress());
+ auto LoopExit = getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
EmitIgnoredExpr(S.getEnsureUpperBound());
// IV = LB;
EmitIgnoredExpr(S.getInit());
// while (idx <= UB) { BODY; ++idx; }
- EmitOMPInnerLoop(S, LoopScope);
+ EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
+ S.getInc(),
+ [&S, LoopExit](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, LoopExit);
+ CGF.EmitStopPoint(&S);
+ },
+ [](CodeGenFunction &) {});
+ EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
- RT.EmitOMPForFinish(*this, S.getLocStart(), ScheduleKind);
- } else
- ErrorUnsupported(&S, "OpenMP loop with requested schedule");
+ RT.emitForStaticFinish(*this, S.getLocStart());
+ } else {
+ // Emit the outer loop, which requests its work chunk [LB..UB] from
+ // runtime and runs the inner loop to process it.
+ EmitOMPForOuterLoop(ScheduleKind, S, LoopScope, Ordered,
+ LB.getAddress(), UB.getAddress(), ST.getAddress(),
+ IL.getAddress(), Chunk);
+ }
+ EmitOMPReductionClauseFinal(S);
+ // Emit final copy of the lastprivate variables if IsLastIter != 0.
+ if (HasLastprivateClause)
+ EmitOMPLastprivateClauseFinal(
+ S, Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
+ }
+ if (isOpenMPSimdDirective(S.getDirectiveKind())) {
+ EmitOMPSimdFinal(S);
}
// We're now done with the loop, so jump to the continuation block.
- EmitBranch(ContBlock);
- EmitBlock(ContBlock, true);
+ if (ContBlock) {
+ EmitBranch(ContBlock);
+ EmitBlock(ContBlock, true);
+ }
}
+ return HasLastprivateClause;
}
void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
- InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
- RunCleanupsScope DirectiveScope(*this);
+ LexicalScope Scope(*this, S.getSourceRange());
+ bool HasLastprivates = false;
+ auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
+ HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen);
- CGDebugInfo *DI = getDebugInfo();
- if (DI)
- DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
+ // Emit an implicit barrier at the end.
+ if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
+ }
+}
- EmitOMPWorksharingLoop(S);
+void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ bool HasLastprivates = false;
+ auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
+ HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
// Emit an implicit barrier at the end.
- CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart(),
- /*IsExplicit*/ false);
- if (DI)
- DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
+ if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
+ }
}
-void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
- llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
+static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
+ const Twine &Name,
+ llvm::Value *Init = nullptr) {
+ auto LVal = CGF.MakeNaturalAlignAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
+ if (Init)
+ CGF.EmitScalarInit(Init, LVal);
+ return LVal;
+}
+
+OpenMPDirectiveKind
+CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
+ auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
+ auto *CS = dyn_cast<CompoundStmt>(Stmt);
+ if (CS && CS->size() > 1) {
+ bool HasLastprivates = false;
+ auto &&CodeGen = [&S, CS, &HasLastprivates](CodeGenFunction &CGF) {
+ auto &C = CGF.CGM.getContext();
+ auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ // Emit helper vars inits.
+ LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
+ CGF.Builder.getInt32(0));
+ auto *GlobalUBVal = CGF.Builder.getInt32(CS->size() - 1);
+ LValue UB =
+ createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
+ LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
+ CGF.Builder.getInt32(1));
+ LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
+ CGF.Builder.getInt32(0));
+ // Loop counter.
+ LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
+ OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
+ OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
+ // Generate condition for loop.
+ BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
+ OK_Ordinary, S.getLocStart(),
+ /*fpContractable=*/false);
+ // Increment for loop counter.
+ UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue,
+ OK_Ordinary, S.getLocStart());
+ auto BodyGen = [CS, &S, &IV](CodeGenFunction &CGF) {
+ // Iterate through all sections and emit a switch construct:
+ // switch (IV) {
+ // case 0:
+ // <SectionStmt[0]>;
+ // break;
+ // ...
+ // case <NumSection> - 1:
+ // <SectionStmt[<NumSection> - 1]>;
+ // break;
+ // }
+ // .omp.sections.exit:
+ auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
+ auto *SwitchStmt = CGF.Builder.CreateSwitch(
+ CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
+ CS->size());
+ unsigned CaseNumber = 0;
+ for (auto *SubStmt : CS->children()) {
+ auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
+ CGF.EmitBlock(CaseBB);
+ SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
+ CGF.EmitStmt(SubStmt);
+ CGF.EmitBranch(ExitBB);
+ ++CaseNumber;
+ }
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
+ };
+
+ CodeGenFunction::OMPPrivateScope LoopScope(CGF);
+ if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_unknown);
+ }
+ CGF.EmitOMPPrivateClause(S, LoopScope);
+ HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
+ CGF.EmitOMPReductionClauseInit(S, LoopScope);
+ (void)LoopScope.Privatize();
+
+ // Emit static non-chunked loop.
+ CGF.CGM.getOpenMPRuntime().emitForInit(
+ CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
+ /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
+ LB.getAddress(), UB.getAddress(), ST.getAddress());
+ // UB = min(UB, GlobalUB);
+ auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
+ auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
+ CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
+ CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
+ // IV = LB;
+ CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
+ // while (idx <= UB) { BODY; ++idx; }
+ CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
+ [](CodeGenFunction &) {});
+ // Tell the runtime we are done.
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
+ CGF.EmitOMPReductionClauseFinal(S);
+
+ // Emit final copy of the lastprivate variables if IsLastIter != 0.
+ if (HasLastprivates)
+ CGF.EmitOMPLastprivateClauseFinal(
+ S, CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getLocStart())));
+ };
+
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen);
+ // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
+ // clause. Otherwise the barrier will be generated by the codegen for the
+ // directive.
+ if (HasLastprivates && S.getSingleClause(OMPC_nowait)) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables.
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_unknown);
+ }
+ return OMPD_sections;
+ }
+ // If only one section is found - no need to generate loop, emit as a single
+ // region.
+ bool HasFirstprivates;
+ // No need to generate reductions for sections with single section region, we
+ // can use original shared variables for all operations.
+ bool HasReductions = !S.getClausesOfKind(OMPC_reduction).empty();
+ // No need to generate lastprivates for sections with single section region,
+ // we can use original shared variable for all calculations with barrier at
+ // the end of the sections.
+ bool HasLastprivates = !S.getClausesOfKind(OMPC_lastprivate).empty();
+ auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {
+ CodeGenFunction::OMPPrivateScope SingleScope(CGF);
+ HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
+ CGF.EmitOMPPrivateClause(S, SingleScope);
+ (void)SingleScope.Privatize();
+
+ CGF.EmitStmt(Stmt);
+ };
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ llvm::None, llvm::None, llvm::None,
+ llvm::None);
+ // Emit barrier for firstprivates, lastprivates or reductions only if
+ // 'sections' directive has 'nowait' clause. Otherwise the barrier will be
+ // generated by the codegen for the directive.
+ if ((HasFirstprivates || HasLastprivates || HasReductions) &&
+ S.getSingleClause(OMPC_nowait)) {
+ // Emit implicit barrier to synchronize threads and avoid data races on
+ // initialization of firstprivate variables.
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown);
+ }
+ return OMPD_single;
}
-void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
- llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
+void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ OpenMPDirectiveKind EmittedAs = EmitSections(S);
+ // Emit an implicit barrier at the end.
+ if (!S.getSingleClause(OMPC_nowait)) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
+ }
}
-void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
- llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
+void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen);
}
-void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
- llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
+void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
+ llvm::SmallVector<const Expr *, 8> CopyprivateVars;
+ llvm::SmallVector<const Expr *, 8> DestExprs;
+ llvm::SmallVector<const Expr *, 8> SrcExprs;
+ llvm::SmallVector<const Expr *, 8> AssignmentOps;
+ // Check if there are any 'copyprivate' clauses associated with this
+ // 'single'
+ // construct.
+ // Build a list of copyprivate variables along with helper expressions
+ // (<source>, <destination>, <destination>=<source> expressions)
+ for (auto &&I = S.getClausesOfKind(OMPC_copyprivate); I; ++I) {
+ auto *C = cast<OMPCopyprivateClause>(*I);
+ CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
+ DestExprs.append(C->destination_exprs().begin(),
+ C->destination_exprs().end());
+ SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
+ AssignmentOps.append(C->assignment_ops().begin(),
+ C->assignment_ops().end());
+ }
+ LexicalScope Scope(*this, S.getSourceRange());
+ // Emit code for 'single' region along with 'copyprivate' clauses
+ bool HasFirstprivates;
+ auto &&CodeGen = [&S, &HasFirstprivates](CodeGenFunction &CGF) {
+ CodeGenFunction::OMPPrivateScope SingleScope(CGF);
+ HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
+ CGF.EmitOMPPrivateClause(S, SingleScope);
+ (void)SingleScope.Privatize();
+
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ CopyprivateVars, DestExprs, SrcExprs,
+ AssignmentOps);
+ // Emit an implicit barrier at the end (to avoid data race on firstprivate
+ // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
+ if ((!S.getSingleClause(OMPC_nowait) || HasFirstprivates) &&
+ CopyprivateVars.empty()) {
+ CGM.getOpenMPRuntime().emitBarrierCall(
+ *this, S.getLocStart(),
+ S.getSingleClause(OMPC_nowait) ? OMPD_unknown : OMPD_single);
+ }
}
void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
- CGM.getOpenMPRuntime().EmitOMPMasterRegion(*this, [&]() -> void {
- InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
- RunCleanupsScope Scope(*this);
- EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
- }, S.getLocStart());
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
- CGM.getOpenMPRuntime().EmitOMPCriticalRegion(
- *this, S.getDirectiveName().getAsString(), [&]() -> void {
- InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
- RunCleanupsScope Scope(*this);
- EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- EnsureInsertPoint();
- }, S.getLocStart());
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitCriticalRegion(
+ *this, S.getDirectiveName().getAsString(), CodeGen, S.getLocStart());
}
-void
-CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
+void CodeGenFunction::EmitOMPParallelForDirective(
+ const OMPParallelForDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'for' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ (void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPWorksharingLoop(S);
+ // Emit implicit barrier at the end of parallel region, but this barrier
+ // is at the end of 'for' directive, so emit it as the implicit barrier for
+ // this 'for' directive.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen);
}
void CodeGenFunction::EmitOMPParallelForSimdDirective(
- const OMPParallelForSimdDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
+ const OMPParallelForSimdDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'for' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ (void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPWorksharingLoop(S);
+ // Emit implicit barrier at the end of parallel region, but this barrier
+ // is at the end of 'for' directive, so emit it as the implicit barrier for
+ // this 'for' directive.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen);
}
void CodeGenFunction::EmitOMPParallelSectionsDirective(
- const OMPParallelSectionsDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
+ const OMPParallelSectionsDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'sections' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ (void)CGF.EmitSections(S);
+ // Emit implicit barrier at the end of parallel region.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen);
}
-void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
- llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
+void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
+ // Emit outlined function for task construct.
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
+ auto *I = CS->getCapturedDecl()->param_begin();
+ auto *PartId = std::next(I);
+ // The first function argument for tasks is a thread id, the second one is a
+ // part id (0 for tied tasks, >=0 for untied task).
+ llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
+ // Get list of private variables.
+ llvm::SmallVector<const Expr *, 8> PrivateVars;
+ llvm::SmallVector<const Expr *, 8> PrivateCopies;
+ for (auto &&I = S.getClausesOfKind(OMPC_private); I; ++I) {
+ auto *C = cast<OMPPrivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ for (auto *IInit : C->private_copies()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
+ PrivateVars.push_back(*IRef);
+ PrivateCopies.push_back(IInit);
+ }
+ ++IRef;
+ }
+ }
+ EmittedAsPrivate.clear();
+ // Get list of firstprivate variables.
+ llvm::SmallVector<const Expr *, 8> FirstprivateVars;
+ llvm::SmallVector<const Expr *, 8> FirstprivateCopies;
+ llvm::SmallVector<const Expr *, 8> FirstprivateInits;
+ for (auto &&I = S.getClausesOfKind(OMPC_firstprivate); I; ++I) {
+ auto *C = cast<OMPFirstprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto IElemInitRef = C->inits().begin();
+ for (auto *IInit : C->private_copies()) {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+ if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
+ FirstprivateVars.push_back(*IRef);
+ FirstprivateCopies.push_back(IInit);
+ FirstprivateInits.push_back(*IElemInitRef);
+ }
+ ++IRef, ++IElemInitRef;
+ }
+ }
+ // Build list of dependences.
+ llvm::SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 8>
+ Dependences;
+ for (auto &&I = S.getClausesOfKind(OMPC_depend); I; ++I) {
+ auto *C = cast<OMPDependClause>(*I);
+ for (auto *IRef : C->varlists()) {
+ Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));
+ }
+ }
+ auto &&CodeGen = [PartId, &S, &PrivateVars, &FirstprivateVars](
+ CodeGenFunction &CGF) {
+ // Set proper addresses for generated private copies.
+ auto *CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ OMPPrivateScope Scope(CGF);
+ if (!PrivateVars.empty() || !FirstprivateVars.empty()) {
+ auto *CopyFn = CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)),
+ CGF.PointerAlignInBytes);
+ auto *PrivatesPtr = CGF.Builder.CreateAlignedLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)),
+ CGF.PointerAlignInBytes);
+ // Map privates.
+ llvm::SmallVector<std::pair<const VarDecl *, llvm::Value *>, 16>
+ PrivatePtrs;
+ llvm::SmallVector<llvm::Value *, 16> CallArgs;
+ CallArgs.push_back(PrivatesPtr);
+ for (auto *E : PrivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ auto *PrivatePtr =
+ CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()));
+ PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ CallArgs.push_back(PrivatePtr);
+ }
+ for (auto *E : FirstprivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ auto *PrivatePtr =
+ CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()));
+ PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
+ CallArgs.push_back(PrivatePtr);
+ }
+ CGF.EmitRuntimeCall(CopyFn, CallArgs);
+ for (auto &&Pair : PrivatePtrs) {
+ auto *Replacement =
+ CGF.Builder.CreateAlignedLoad(Pair.second, CGF.PointerAlignInBytes);
+ Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
+ }
+ }
+ (void)Scope.Privatize();
+ if (*PartId) {
+ // TODO: emit code for untied tasks.
+ }
+ CGF.EmitStmt(CS->getCapturedStmt());
+ };
+ auto OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
+ S, *I, OMPD_task, CodeGen);
+ // Check if we should emit tied or untied task.
+ bool Tied = !S.getSingleClause(OMPC_untied);
+ // Check if the task is final
+ llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
+ if (auto *Clause = S.getSingleClause(OMPC_final)) {
+ // If the condition constant folds and can be elided, try to avoid emitting
+ // the condition and the dead arm of the if/else.
+ auto *Cond = cast<OMPFinalClause>(Clause)->getCondition();
+ bool CondConstant;
+ if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
+ Final.setInt(CondConstant);
+ else
+ Final.setPointer(EvaluateExprAsBool(Cond));
+ } else {
+ // By default the task is not final.
+ Final.setInt(/*IntVal=*/false);
+ }
+ auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ const Expr *IfCond = nullptr;
+ if (auto C = S.getSingleClause(OMPC_if)) {
+ IfCond = cast<OMPIfClause>(C)->getCondition();
+ }
+ CGM.getOpenMPRuntime().emitTaskCall(
+ *this, S.getLocStart(), S, Tied, Final, OutlinedFn, SharedsTy,
+ CapturedStruct, IfCond, PrivateVars, PrivateCopies, FirstprivateVars,
+ FirstprivateCopies, FirstprivateInits, Dependences);
}
-void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
- llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
+void CodeGenFunction::EmitOMPTaskyieldDirective(
+ const OMPTaskyieldDirective &S) {
+ CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getLocStart());
}
void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
- CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart());
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_barrier);
+}
+
+void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
+ CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getLocStart());
}
-void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
- llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
+void CodeGenFunction::EmitOMPTaskgroupDirective(
+ const OMPTaskgroupDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
- CGM.getOpenMPRuntime().EmitOMPFlush(
- *this, [&]() -> ArrayRef<const Expr *> {
- if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {
- auto FlushClause = cast<OMPFlushClause>(C);
- return llvm::makeArrayRef(FlushClause->varlist_begin(),
- FlushClause->varlist_end());
- }
- return llvm::None;
- }(),
- S.getLocStart());
+ CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> {
+ if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {
+ auto FlushClause = cast<OMPFlushClause>(C);
+ return llvm::makeArrayRef(FlushClause->varlist_begin(),
+ FlushClause->varlist_end());
+ }
+ return llvm::None;
+ }(), S.getLocStart());
+}
+
+void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGF.EnsureInsertPoint();
+ };
+ CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart());
+}
+
+static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
+ QualType SrcType, QualType DestType) {
+ assert(CGF.hasScalarEvaluationKind(DestType) &&
+ "DestType must have scalar evaluation kind.");
+ assert(!Val.isAggregate() && "Must be a scalar or complex.");
+ return Val.isScalar()
+ ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType)
+ : CGF.EmitComplexToScalarConversion(Val.getComplexVal(), SrcType,
+ DestType);
+}
+
+static CodeGenFunction::ComplexPairTy
+convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
+ QualType DestType) {
+ assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
+ "DestType must have complex evaluation kind.");
+ CodeGenFunction::ComplexPairTy ComplexVal;
+ if (Val.isScalar()) {
+ // Convert the input element to the element type of the complex.
+ auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
+ auto ScalarVal =
+ CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestElementType);
+ ComplexVal = CodeGenFunction::ComplexPairTy(
+ ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
+ } else {
+ assert(Val.isComplex() && "Must be a scalar or complex.");
+ auto SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
+ auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
+ ComplexVal.first = CGF.EmitScalarConversion(
+ Val.getComplexVal().first, SrcElementType, DestElementType);
+ ComplexVal.second = CGF.EmitScalarConversion(
+ Val.getComplexVal().second, SrcElementType, DestElementType);
+ }
+ return ComplexVal;
+}
+
+static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst,
+ LValue LVal, RValue RVal) {
+ if (LVal.isGlobalReg()) {
+ CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
+ } else {
+ CGF.EmitAtomicStore(RVal, LVal, IsSeqCst ? llvm::SequentiallyConsistent
+ : llvm::Monotonic,
+ LVal.isVolatile(), /*IsInit=*/false);
+ }
+}
+
+static void emitSimpleStore(CodeGenFunction &CGF, LValue LVal, RValue RVal,
+ QualType RValTy) {
+ switch (CGF.getEvaluationKind(LVal.getType())) {
+ case TEK_Scalar:
+ CGF.EmitStoreThroughLValue(
+ RValue::get(convertToScalarValue(CGF, RVal, RValTy, LVal.getType())),
+ LVal);
+ break;
+ case TEK_Complex:
+ CGF.EmitStoreOfComplex(
+ convertToComplexValue(CGF, RVal, RValTy, LVal.getType()), LVal,
+ /*isInit=*/false);
+ break;
+ case TEK_Aggregate:
+ llvm_unreachable("Must be a scalar or complex.");
+ }
+}
+
+static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
+ const Expr *X, const Expr *V,
+ SourceLocation Loc) {
+ // v = x;
+ assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
+ assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
+ LValue XLValue = CGF.EmitLValue(X);
+ LValue VLValue = CGF.EmitLValue(V);
+ RValue Res = XLValue.isGlobalReg()
+ ? CGF.EmitLoadOfLValue(XLValue, Loc)
+ : CGF.EmitAtomicLoad(XLValue, Loc,
+ IsSeqCst ? llvm::SequentiallyConsistent
+ : llvm::Monotonic,
+ XLValue.isVolatile());
+ // OpenMP, 2.12.6, atomic Construct
+ // Any atomic construct with a seq_cst clause forces the atomically
+ // performed operation to include an implicit flush operation without a
+ // list.
+ if (IsSeqCst)
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
+ emitSimpleStore(CGF,VLValue, Res, X->getType().getNonReferenceType());
+}
+
+static void EmitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
+ const Expr *X, const Expr *E,
+ SourceLocation Loc) {
+ // x = expr;
+ assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
+ emitSimpleAtomicStore(CGF, IsSeqCst, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
+ // OpenMP, 2.12.6, atomic Construct
+ // Any atomic construct with a seq_cst clause forces the atomically
+ // performed operation to include an implicit flush operation without a
+ // list.
+ if (IsSeqCst)
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
+}
+
+static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
+ RValue Update,
+ BinaryOperatorKind BO,
+ llvm::AtomicOrdering AO,
+ bool IsXLHSInRHSPart) {
+ auto &Context = CGF.CGM.getContext();
+ // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
+ // expression is simple and atomic is allowed for the given type for the
+ // target platform.
+ if (BO == BO_Comma || !Update.isScalar() ||
+ !Update.getScalarVal()->getType()->isIntegerTy() ||
+ !X.isSimple() || (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
+ (Update.getScalarVal()->getType() !=
+ X.getAddress()->getType()->getPointerElementType())) ||
+ !X.getAddress()->getType()->getPointerElementType()->isIntegerTy() ||
+ !Context.getTargetInfo().hasBuiltinAtomic(
+ Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
+ return std::make_pair(false, RValue::get(nullptr));
+
+ llvm::AtomicRMWInst::BinOp RMWOp;
+ switch (BO) {
+ case BO_Add:
+ RMWOp = llvm::AtomicRMWInst::Add;
+ break;
+ case BO_Sub:
+ if (!IsXLHSInRHSPart)
+ return std::make_pair(false, RValue::get(nullptr));
+ RMWOp = llvm::AtomicRMWInst::Sub;
+ break;
+ case BO_And:
+ RMWOp = llvm::AtomicRMWInst::And;
+ break;
+ case BO_Or:
+ RMWOp = llvm::AtomicRMWInst::Or;
+ break;
+ case BO_Xor:
+ RMWOp = llvm::AtomicRMWInst::Xor;
+ break;
+ case BO_LT:
+ RMWOp = X.getType()->hasSignedIntegerRepresentation()
+ ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
+ : llvm::AtomicRMWInst::Max)
+ : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
+ : llvm::AtomicRMWInst::UMax);
+ break;
+ case BO_GT:
+ RMWOp = X.getType()->hasSignedIntegerRepresentation()
+ ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
+ : llvm::AtomicRMWInst::Min)
+ : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
+ : llvm::AtomicRMWInst::UMin);
+ break;
+ case BO_Assign:
+ RMWOp = llvm::AtomicRMWInst::Xchg;
+ break;
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LAnd:
+ case BO_LOr:
+ return std::make_pair(false, RValue::get(nullptr));
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Comma:
+ llvm_unreachable("Unsupported atomic update operation");
+ }
+ auto *UpdateVal = Update.getScalarVal();
+ if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
+ UpdateVal = CGF.Builder.CreateIntCast(
+ IC, X.getAddress()->getType()->getPointerElementType(),
+ X.getType()->hasSignedIntegerRepresentation());
+ }
+ auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(), UpdateVal, AO);
+ return std::make_pair(true, RValue::get(Res));
+}
+
+std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
+ LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
+ llvm::AtomicOrdering AO, SourceLocation Loc,
+ const llvm::function_ref<RValue(RValue)> &CommonGen) {
+ // Update expressions are allowed to have the following forms:
+ // x binop= expr; -> xrval + expr;
+ // x++, ++x -> xrval + 1;
+ // x--, --x -> xrval - 1;
+ // x = x binop expr; -> xrval binop expr
+ // x = expr Op x; - > expr binop xrval;
+ auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
+ if (!Res.first) {
+ if (X.isGlobalReg()) {
+ // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
+ // 'xrval'.
+ EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
+ } else {
+ // Perform compare-and-swap procedure.
+ EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
+ }
+ }
+ return Res;
+}
+
+static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
+ const Expr *X, const Expr *E,
+ const Expr *UE, bool IsXLHSInRHSPart,
+ SourceLocation Loc) {
+ assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
+ "Update expr in 'atomic update' must be a binary operator.");
+ auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
+ // Update expressions are allowed to have the following forms:
+ // x binop= expr; -> xrval + expr;
+ // x++, ++x -> xrval + 1;
+ // x--, --x -> xrval - 1;
+ // x = x binop expr; -> xrval binop expr
+ // x = expr Op x; - > expr binop xrval;
+ assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
+ LValue XLValue = CGF.EmitLValue(X);
+ RValue ExprRValue = CGF.EmitAnyExpr(E);
+ auto AO = IsSeqCst ? llvm::SequentiallyConsistent : llvm::Monotonic;
+ auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
+ auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
+ auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
+ auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
+ auto Gen =
+ [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) -> RValue {
+ CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
+ CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
+ return CGF.EmitAnyExpr(UE);
+ };
+ (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
+ XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
+ // OpenMP, 2.12.6, atomic Construct
+ // Any atomic construct with a seq_cst clause forces the atomically
+ // performed operation to include an implicit flush operation without a
+ // list.
+ if (IsSeqCst)
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
+}
+
+static RValue convertToType(CodeGenFunction &CGF, RValue Value,
+ QualType SourceType, QualType ResType) {
+ switch (CGF.getEvaluationKind(ResType)) {
+ case TEK_Scalar:
+ return RValue::get(convertToScalarValue(CGF, Value, SourceType, ResType));
+ case TEK_Complex: {
+ auto Res = convertToComplexValue(CGF, Value, SourceType, ResType);
+ return RValue::getComplex(Res.first, Res.second);
+ }
+ case TEK_Aggregate:
+ break;
+ }
+ llvm_unreachable("Must be a scalar or complex.");
+}
+
+static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
+ bool IsPostfixUpdate, const Expr *V,
+ const Expr *X, const Expr *E,
+ const Expr *UE, bool IsXLHSInRHSPart,
+ SourceLocation Loc) {
+ assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
+ assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
+ RValue NewVVal;
+ LValue VLValue = CGF.EmitLValue(V);
+ LValue XLValue = CGF.EmitLValue(X);
+ RValue ExprRValue = CGF.EmitAnyExpr(E);
+ auto AO = IsSeqCst ? llvm::SequentiallyConsistent : llvm::Monotonic;
+ QualType NewVValType;
+ if (UE) {
+ // 'x' is updated with some additional value.
+ assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
+ "Update expr in 'atomic capture' must be a binary operator.");
+ auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
+ // Update expressions are allowed to have the following forms:
+ // x binop= expr; -> xrval + expr;
+ // x++, ++x -> xrval + 1;
+ // x--, --x -> xrval - 1;
+ // x = x binop expr; -> xrval binop expr
+ // x = expr Op x; - > expr binop xrval;
+ auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
+ auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
+ auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
+ NewVValType = XRValExpr->getType();
+ auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
+ auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
+ IsSeqCst, IsPostfixUpdate](RValue XRValue) -> RValue {
+ CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
+ CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
+ RValue Res = CGF.EmitAnyExpr(UE);
+ NewVVal = IsPostfixUpdate ? XRValue : Res;
+ return Res;
+ };
+ auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
+ XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
+ if (Res.first) {
+ // 'atomicrmw' instruction was generated.
+ if (IsPostfixUpdate) {
+ // Use old value from 'atomicrmw'.
+ NewVVal = Res.second;
+ } else {
+ // 'atomicrmw' does not provide new value, so evaluate it using old
+ // value of 'x'.
+ CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
+ CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
+ NewVVal = CGF.EmitAnyExpr(UE);
+ }
+ }
+ } else {
+ // 'x' is simply rewritten with some 'expr'.
+ NewVValType = X->getType().getNonReferenceType();
+ ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
+ X->getType().getNonReferenceType());
+ auto &&Gen = [&CGF, &NewVVal, ExprRValue](RValue XRValue) -> RValue {
+ NewVVal = XRValue;
+ return ExprRValue;
+ };
+ // Try to perform atomicrmw xchg, otherwise simple exchange.
+ auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
+ XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
+ Loc, Gen);
+ if (Res.first) {
+ // 'atomicrmw' instruction was generated.
+ NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
+ }
+ }
+ // Emit post-update store to 'v' of old/new 'x' value.
+ emitSimpleStore(CGF, VLValue, NewVVal, NewVValType);
+ // OpenMP, 2.12.6, atomic Construct
+ // Any atomic construct with a seq_cst clause forces the atomically
+ // performed operation to include an implicit flush operation without a
+ // list.
+ if (IsSeqCst)
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
}
-void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
- llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
+static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
+ bool IsSeqCst, bool IsPostfixUpdate,
+ const Expr *X, const Expr *V, const Expr *E,
+ const Expr *UE, bool IsXLHSInRHSPart,
+ SourceLocation Loc) {
+ switch (Kind) {
+ case OMPC_read:
+ EmitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc);
+ break;
+ case OMPC_write:
+ EmitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc);
+ break;
+ case OMPC_unknown:
+ case OMPC_update:
+ EmitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc);
+ break;
+ case OMPC_capture:
+ EmitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE,
+ IsXLHSInRHSPart, Loc);
+ break;
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_reduction:
+ case OMPC_safelen:
+ case OMPC_collapse:
+ case OMPC_default:
+ case OMPC_seq_cst:
+ case OMPC_shared:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_flush:
+ case OMPC_proc_bind:
+ case OMPC_schedule:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_threadprivate:
+ case OMPC_depend:
+ case OMPC_mergeable:
+ llvm_unreachable("Clause is not allowed in 'omp atomic'.");
+ }
}
-void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
- llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
+void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
+ bool IsSeqCst = S.getSingleClause(/*K=*/OMPC_seq_cst);
+ OpenMPClauseKind Kind = OMPC_unknown;
+ for (auto *C : S.clauses()) {
+ // Find first clause (skip seq_cst clause, if it is first).
+ if (C->getClauseKind() != OMPC_seq_cst) {
+ Kind = C->getClauseKind();
+ break;
+ }
+ }
+
+ const auto *CS =
+ S.getAssociatedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS)) {
+ enterFullExpression(EWC);
+ }
+ // Processing for statements under 'atomic capture'.
+ if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
+ for (const auto *C : Compound->body()) {
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(C)) {
+ enterFullExpression(EWC);
+ }
+ }
+ }
+
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S, Kind, IsSeqCst](CodeGenFunction &CGF) {
+ EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
+ S.getV(), S.getExpr(), S.getUpdateExpr(),
+ S.isXLHSInRHSPart(), S.getLocStart());
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
}
void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
@@ -703,3 +2101,23 @@ void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");
}
+void CodeGenFunction::EmitOMPCancellationPointDirective(
+ const OMPCancellationPointDirective &S) {
+ CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
+ S.getCancelRegion());
+}
+
+void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
+ CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(),
+ S.getCancelRegion());
+}
+
+CodeGenFunction::JumpDest
+CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
+ if (Kind == OMPD_parallel || Kind == OMPD_task)
+ return ReturnBlock;
+ else if (Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections)
+ return BreakContinueStack.empty() ? JumpDest()
+ : BreakContinueStack.back().BreakBlock;
+ return JumpDest();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
index bd280ea..e3df5a4 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
@@ -18,7 +18,7 @@
using namespace clang;
using namespace CodeGen;
-static llvm::Constant *
+static llvm::GlobalVariable *
GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
const CXXRecordDecl *MostDerivedClass,
const VTTVTable &VTable,
@@ -47,8 +47,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int64Ty = CGM.Int64Ty;
llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
-
- SmallVector<llvm::Constant *, 8> VTables;
+
+ SmallVector<llvm::GlobalVariable *, 8> VTables;
SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
for (const VTTVTable *i = Builder.getVTTVTables().begin(),
*e = Builder.getVTTVTables().end(); i != e; ++i) {
@@ -61,7 +61,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
for (const VTTComponent *i = Builder.getVTTComponents().begin(),
*e = Builder.getVTTComponents().end(); i != e; ++i) {
const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
- llvm::Constant *VTable = VTables[i->VTableIndex];
+ llvm::GlobalVariable *VTable = VTables[i->VTableIndex];
uint64_t AddressPoint;
if (VTTVT.getBase() == RD) {
// Just get the address point for the regular vtable.
@@ -79,8 +79,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
llvm::ConstantInt::get(Int64Ty, AddressPoint)
};
- llvm::Constant *Init =
- llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs);
+ llvm::Constant *Init = llvm::ConstantExpr::getInBoundsGetElementPtr(
+ VTable->getValueType(), VTable, Idxs);
Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
@@ -94,6 +94,9 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
// Set the correct linkage.
VTT->setLinkage(Linkage);
+ if (CGM.supportsCOMDAT() && VTT->isWeakForLinker())
+ VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
+
// Set the right visibility.
CGM.setGlobalVisibility(VTT, RD);
}
@@ -174,4 +177,3 @@ CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
return I->second;
}
-
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index acb2a56..e36051c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -123,8 +123,8 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
// no-op thunk for the regular definition) call va_start/va_end.
// There's a bit of per-call overhead for this solution, but it's
// better for codesize if the definition is long.
-void CodeGenFunction::GenerateVarArgsThunk(
- llvm::Function *Fn,
+llvm::Function *
+CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@@ -184,6 +184,8 @@ void CodeGenFunction::GenerateVarArgsThunk(
}
}
}
+
+ return Fn;
}
void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
@@ -362,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);
@@ -374,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,
@@ -447,17 +442,25 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
// expensive/sucky at the moment, so don't generate the thunk unless
// we have to.
// FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly.
- if (!UseAvailableExternallyLinkage) {
- CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
- !Thunk.Return.isEmpty());
- }
+ if (UseAvailableExternallyLinkage)
+ return;
+ ThunkFn =
+ CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
} else {
// Normal thunk body generation.
- CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
- !Thunk.Return.isEmpty());
+ 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()));
}
void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD,
@@ -666,6 +669,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
VTLayout->getNumVTableThunks(), RTTI);
VTable->setInitializer(Init);
+ CGM.EmitVTableBitSetEntries(VTable, *VTLayout.get());
+
return VTable;
}
@@ -697,7 +702,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
llvm::Function::InternalLinkage;
return llvm::GlobalVariable::ExternalLinkage;
-
+
case TSK_ImplicitInstantiation:
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
@@ -738,7 +743,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return DiscardableODRLinkage;
case TSK_ExplicitInstantiationDeclaration:
- llvm_unreachable("Should not have been asked to emit this");
+ return llvm::GlobalVariable::ExternalLinkage;
case TSK_ExplicitInstantiationDefinition:
return NonDiscardableODRLinkage;
@@ -747,19 +752,13 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
llvm_unreachable("Invalid TemplateSpecializationKind!");
}
-/// This is a callback from Sema to tell us that it believes that a
-/// particular v-table is required to be emitted in this translation
-/// unit.
+/// This is a callback from Sema to tell us that that a particular v-table is
+/// required to be emitted in this translation unit.
///
-/// The reason we don't simply trust this callback is because Sema
-/// will happily report that something is used even when it's used
-/// only in code that we don't actually have to emit.
-///
-/// \param isRequired - if true, the v-table is mandatory, e.g.
-/// because the translation unit defines the key function
-void CodeGenModule::EmitVTable(CXXRecordDecl *theClass, bool isRequired) {
- if (!isRequired) return;
-
+/// This is only called for vtables that _must_ be emitted (mainly due to key
+/// functions). For weak vtables, CodeGen tracks when they are needed and
+/// emits them as-needed.
+void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) {
VTables.GenerateClassData(theClass);
}
@@ -840,3 +839,58 @@ void CodeGenModule::EmitDeferredVTables() {
"deferred extra v-tables during v-table emission?");
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) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFINVCall) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) &&
+ !LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast))
+ return;
+
+ CharUnits PointerWidth =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+
+ std::vector<llvm::MDTuple *> BitsetEntries;
+ // Create a bit set entry for each address point.
+ for (auto &&AP : VTLayout.getAddressPoints()) {
+ if (IsCFIBlacklistedRecord(AP.first.getBase()))
+ continue;
+
+ BitsetEntries.push_back(CreateVTableBitSetEntry(
+ VTable, PointerWidth * AP.second, AP.first.getBase()));
+ }
+
+ // Sort the bit set entries for determinism.
+ std::sort(BitsetEntries.begin(), BitsetEntries.end(), [](llvm::MDTuple *T1,
+ llvm::MDTuple *T2) {
+ if (T1 == T2)
+ return false;
+
+ StringRef S1 = cast<llvm::MDString>(T1->getOperand(0))->getString();
+ StringRef S2 = cast<llvm::MDString>(T2->getOperand(0))->getString();
+ if (S1 < S2)
+ return true;
+ if (S1 != S2)
+ return false;
+
+ uint64_t Offset1 = cast<llvm::ConstantInt>(
+ cast<llvm::ConstantAsMetadata>(T1->getOperand(2))
+ ->getValue())->getZExtValue();
+ uint64_t Offset2 = cast<llvm::ConstantInt>(
+ cast<llvm::ConstantAsMetadata>(T2->getOperand(2))
+ ->getValue())->getZExtValue();
+ assert(Offset1 != Offset2);
+ return Offset1 < Offset2;
+ });
+
+ llvm::NamedMDNode *BitsetsMD =
+ getModule().getOrInsertNamedMetadata("llvm.bitsets");
+ for (auto BitsetEntry : BitsetEntries)
+ BitsetsMD->addOperand(BitsetEntry);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
index 82cd949..9205591 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
@@ -19,6 +19,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/Type.h"
namespace llvm {
class Constant;
@@ -299,6 +300,7 @@ public:
LValue R;
R.LVType = Simple;
+ assert(address->getType()->isPointerTy());
R.V = address;
R.Initialize(type, qs, alignment, TBAAInfo);
return R;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
index 12189ae..755e8aa 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -20,6 +20,8 @@
#include "CodeGenModule.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/PreprocessorOptions.h"
using namespace clang;
using namespace CodeGen;
@@ -29,7 +31,10 @@ CodeGenABITypes::CodeGenABITypes(ASTContext &C,
const llvm::DataLayout &TD,
CoverageSourceInfo *CoverageInfo)
: CGO(new CodeGenOptions),
- CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics(),
+ HSO(new HeaderSearchOptions),
+ PPO(new PreprocessorOptions),
+ CGM(new CodeGen::CodeGenModule(C, *HSO, *PPO, *CGO,
+ M, TD, C.getDiagnostics(),
CoverageInfo)) {
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
index a6f6fde..0e7b6d8 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
@@ -46,7 +46,7 @@ namespace clang {
const CodeGenOptions &CodeGenOpts;
const TargetOptions &TargetOpts;
const LangOptions &LangOpts;
- raw_ostream *AsmOutStream;
+ raw_pwrite_stream *AsmOutStream;
ASTContext *Context;
Timer LLVMIRGeneration;
@@ -56,18 +56,20 @@ namespace clang {
std::unique_ptr<llvm::Module> TheModule, LinkModule;
public:
- BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags,
- const CodeGenOptions &compopts,
- const TargetOptions &targetopts,
- const LangOptions &langopts, bool TimePasses,
- const std::string &infile, llvm::Module *LinkModule,
- raw_ostream *OS, LLVMContext &C,
+ BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
+ const HeaderSearchOptions &HeaderSearchOpts,
+ const PreprocessorOptions &PPOpts,
+ const CodeGenOptions &CodeGenOpts,
+ const TargetOptions &TargetOpts,
+ const LangOptions &LangOpts, bool TimePasses,
+ const std::string &InFile, llvm::Module *LinkModule,
+ raw_pwrite_stream *OS, LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr)
- : Diags(_Diags), Action(action), CodeGenOpts(compopts),
- TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
+ : Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
+ TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS),
Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"),
- Gen(CreateLLVMCodeGen(Diags, infile, compopts,
- targetopts, C, CoverageInfo)),
+ Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
+ CodeGenOpts, C, CoverageInfo)),
LinkModule(LinkModule) {
llvm::TimePassesIsEnabled = TimePasses;
}
@@ -80,6 +82,11 @@ namespace clang {
}
void Initialize(ASTContext &Ctx) override {
+ if (Context) {
+ assert(Context == &Ctx);
+ return;
+ }
+
Context = &Ctx;
if (llvm::TimePassesIsEnabled)
@@ -196,8 +203,8 @@ namespace clang {
Gen->CompleteTentativeDefinition(D);
}
- void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) override {
- Gen->HandleVTable(RD, DefinitionRequired);
+ void HandleVTable(CXXRecordDecl *RD) override {
+ Gen->HandleVTable(RD);
}
void HandleLinkerOptionPragma(llvm::StringRef Opts) override {
@@ -430,13 +437,16 @@ void BackendConsumer::EmitOptimizationMessage(
FileManager &FileMgr = SourceMgr.getFileManager();
StringRef Filename;
unsigned Line, Column;
- D.getLocation(&Filename, &Line, &Column);
SourceLocation DILoc;
- const FileEntry *FE = FileMgr.getFile(Filename);
- if (FE && Line > 0) {
- // If -gcolumn-info was not used, Column will be 0. This upsets the
- // source manager, so pass 1 if Column is not set.
- DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+
+ if (D.isLocationAvailable()) {
+ D.getLocation(&Filename, &Line, &Column);
+ const FileEntry *FE = FileMgr.getFile(Filename);
+ if (FE && Line > 0) {
+ // If -gcolumn-info was not used, Column will be 0. This upsets the
+ // source manager, so pass 1 if Column is not set.
+ DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+ }
}
// If a location isn't available, try to approximate it using the associated
@@ -451,7 +461,7 @@ void BackendConsumer::EmitOptimizationMessage(
<< AddFlagValue(D.getPassName() ? D.getPassName() : "")
<< D.getMsg().str();
- if (DILoc.isInvalid())
+ if (DILoc.isInvalid() && D.isLocationAvailable())
// If we were not able to translate the file:line:col information
// back to a SourceLocation, at least emit a note stating that
// we could not translate this location. This can happen in the
@@ -602,9 +612,8 @@ llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
return VMContext;
}
-static raw_ostream *GetOutputStream(CompilerInstance &CI,
- StringRef InFile,
- BackendAction Action) {
+static raw_pwrite_stream *
+GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
switch (Action) {
case Backend_EmitAssembly:
return CI.createDefaultOutputFile(false, InFile, "s");
@@ -626,7 +635,7 @@ static raw_ostream *GetOutputStream(CompilerInstance &CI,
std::unique_ptr<ASTConsumer>
CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
BackendAction BA = static_cast<BackendAction>(Act);
- std::unique_ptr<raw_ostream> OS(GetOutputStream(CI, InFile, BA));
+ raw_pwrite_stream *OS = GetOutputStream(CI, InFile, BA);
if (BA != Backend_EmitNothing && !OS)
return nullptr;
@@ -643,14 +652,14 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return nullptr;
}
- ErrorOr<llvm::Module *> ModuleOrErr =
+ ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr =
getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
if (std::error_code EC = ModuleOrErr.getError()) {
CI.getDiagnostics().Report(diag::err_cannot_open_file)
<< LinkBCFile << EC.message();
return nullptr;
}
- LinkModuleToUse = ModuleOrErr.get();
+ LinkModuleToUse = ModuleOrErr.get().release();
}
CoverageSourceInfo *CoverageInfo = nullptr;
@@ -661,19 +670,26 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<PPCallbacks>(CoverageInfo));
}
std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
- BA, CI.getDiagnostics(), CI.getCodeGenOpts(), CI.getTargetOpts(),
+ BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
+ CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile,
- LinkModuleToUse, OS.release(), *VMContext, CoverageInfo));
+ LinkModuleToUse, OS, *VMContext, CoverageInfo));
BEConsumer = Result.get();
return std::move(Result);
}
+static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM,
+ void *Context,
+ unsigned LocCookie) {
+ SM.print(nullptr, llvm::errs());
+}
+
void CodeGenAction::ExecuteAction() {
// If this is an IR file, we have to treat it specially.
if (getCurrentFileKind() == IK_LLVM_IR) {
BackendAction BA = static_cast<BackendAction>(Act);
CompilerInstance &CI = getCompilerInstance();
- raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA);
+ raw_pwrite_stream *OS = GetOutputStream(CI, getCurrentFile(), BA);
if (BA != Backend_EmitNothing && !OS)
return;
@@ -710,14 +726,14 @@ void CodeGenAction::ExecuteAction() {
}
const TargetOptions &TargetOpts = CI.getTargetOpts();
if (TheModule->getTargetTriple() != TargetOpts.Triple) {
- unsigned DiagID = CI.getDiagnostics().getCustomDiagID(
- DiagnosticsEngine::Warning,
- "overriding the module target triple with %0");
-
- CI.getDiagnostics().Report(SourceLocation(), DiagID) << TargetOpts.Triple;
+ CI.getDiagnostics().Report(SourceLocation(),
+ diag::warn_fe_override_module)
+ << TargetOpts.Triple;
TheModule->setTargetTriple(TargetOpts.Triple);
}
+ LLVMContext &Ctx = TheModule->getContext();
+ Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
CI.getLangOpts(), CI.getTarget().getTargetDescription(),
TheModule.get(), BA, OS);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
index 826171a..ec3c75c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCleanup.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
@@ -40,15 +41,16 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
CurFn(nullptr), CapturedStmtInfo(nullptr),
SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false),
CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false),
- BlockInfo(nullptr), BlockPointer(nullptr),
+ IsOutlinedSEHHelper(false), BlockInfo(nullptr), BlockPointer(nullptr),
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(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),
@@ -69,6 +71,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
if (CGM.getCodeGenOpts().NoSignedZeros) {
FMF.setNoSignedZeros();
}
+ if (CGM.getCodeGenOpts().ReciprocalMath) {
+ FMF.setAllowReciprocal();
+ }
Builder.SetFastMathFlags(FMF);
}
@@ -82,7 +87,7 @@ CodeGenFunction::~CodeGenFunction() {
destroyBlockInfos(FirstBlockInfo);
if (getLangOpts().OpenMP) {
- CGM.getOpenMPRuntime().FunctionFinished(*this);
+ CGM.getOpenMPRuntime().functionFinished(*this);
}
}
@@ -239,17 +244,18 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// parameters. Do this in whatever block we're currently in; it's
// important to do this before we enter the return block or return
// edges will be *really* confused.
- bool EmitRetDbgLoc = true;
- if (EHStack.stable_begin() != PrologueCleanupDepth) {
- PopCleanupBlocks(PrologueCleanupDepth);
-
+ bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth;
+ bool HasOnlyLifetimeMarkers =
+ HasCleanups && EHStack.containsOnlyLifetimeMarkers(PrologueCleanupDepth);
+ bool EmitRetDbgLoc = !HasCleanups || HasOnlyLifetimeMarkers;
+ if (HasCleanups) {
// Make sure the line table doesn't jump back into the body for
// the ret after it's been at EndLoc.
- EmitRetDbgLoc = false;
-
if (CGDebugInfo *DI = getDebugInfo())
if (OnlySimpleReturnStmts)
DI->EmitLocation(Builder, EndLoc);
+
+ PopCleanupBlocks(PrologueCleanupDepth);
}
// Emit function epilog (to return).
@@ -278,6 +284,20 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
Builder.ClearInsertionPoint();
}
+ // 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
+ // no holes.
+ SmallVector<llvm::Value *, 4> EscapeArgs;
+ EscapeArgs.resize(EscapedLocals.size());
+ for (auto &Pair : EscapedLocals)
+ EscapeArgs[Pair.second] = Pair.first;
+ llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::localescape);
+ CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
+ }
+
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = nullptr;
@@ -588,6 +608,22 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (CGM.isInSanitizerBlacklist(Fn, Loc))
SanOpts.clear();
+ if (D) {
+ // Apply the no_sanitize* attributes to SanOpts.
+ for (auto Attr : D->specific_attrs<NoSanitizeAttr>())
+ SanOpts.Mask &= ~Attr->getMask();
+ }
+
+ // Apply sanitizer attributes to the function.
+ if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress))
+ Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+ if (SanOpts.has(SanitizerKind::Thread))
+ Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (SanOpts.has(SanitizerKind::Memory))
+ Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+ if (SanOpts.has(SanitizerKind::SafeStack))
+ Fn->addFnAttr(llvm::Attribute::SafeStack);
+
// Pass inline keyword to optimizer if it appears explicitly on any
// declaration. Also, in the case of -fno-inline attach NoInline
// attribute to all function that are not marked AlwaysInline.
@@ -679,7 +715,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *Addr = Builder.CreateStructGEP(EI, Idx);
+ llvm::Value *Addr = Builder.CreateStructGEP(nullptr, EI, Idx);
ReturnValue = Builder.CreateLoad(Addr, "agg.result");
} else {
ReturnValue = CreateIRTemp(RetTy, "retval");
@@ -753,8 +789,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
const Stmt *Body) {
- RegionCounter Cnt = getPGORegionCounter(Body);
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(Body);
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
@@ -766,7 +801,7 @@ void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
/// emit a branch around the instrumentation code. When not instrumenting,
/// this just calls EmitBlock().
void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
- RegionCounter &Cnt) {
+ const Stmt *S) {
llvm::BasicBlock *SkipCountBB = nullptr;
if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileInstrGenerate) {
// When instrumenting for profiling, the fallthrough to certain
@@ -776,7 +811,9 @@ void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
EmitBranch(SkipCountBB);
}
EmitBlock(BB);
- Cnt.beginRegion(Builder, /*AddIncomingFallThrough=*/true);
+ uint64_t CurrentCount = getCurrentProfileCount();
+ incrementProfileCounter(S);
+ setCurrentProfileCount(getCurrentProfileCount() + CurrentCount);
if (SkipCountBB)
EmitBlock(SkipCountBB);
}
@@ -801,17 +838,6 @@ static void TryMarkNoThrow(llvm::Function *F) {
F->setDoesNotThrow();
}
-static void EmitSizedDeallocationFunction(CodeGenFunction &CGF,
- const FunctionDecl *UnsizedDealloc) {
- // This is a weak discardable definition of the sized deallocation function.
- CGF.CurFn->setLinkage(llvm::Function::LinkOnceAnyLinkage);
-
- // Call the unsized deallocation function and forward the first argument
- // unchanged.
- llvm::Constant *Unsized = CGF.CGM.GetAddrOfFunction(UnsizedDealloc);
- CGF.Builder.CreateCall(Unsized, &*CGF.CurFn->arg_begin());
-}
-
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -832,7 +858,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
ResTy = CGM.getContext().VoidPtrTy;
CGM.getCXXABI().buildThisParam(*this, Args);
}
-
+
Args.append(FD->param_begin(), FD->param_end());
if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)))
@@ -866,9 +892,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
else if (isa<CXXConstructorDecl>(FD))
EmitConstructorBody(Args);
else if (getLangOpts().CUDA &&
- !CGM.getCodeGenOpts().CUDAIsDevice &&
+ !getLangOpts().CUDAIsDevice &&
FD->hasAttr<CUDAGlobalAttr>())
- CGM.getCUDARuntime().EmitDeviceStubBody(*this, Args);
+ CGM.getCUDARuntime().emitDeviceStub(*this, Args);
else if (isa<CXXConversionDecl>(FD) &&
cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion()) {
// The lambda conversion to block pointer is special; the semantics can't be
@@ -887,11 +913,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
emitImplicitAssignmentOperatorBody(Args);
} else if (Stmt *Body = FD->getBody()) {
EmitFunctionBody(Args, Body);
- } else if (FunctionDecl *UnsizedDealloc =
- FD->getCorrespondingUnsizedGlobalDeallocationFunction()) {
- // Global sized deallocation functions get an implicit weak definition if
- // they don't have an explicit definition.
- EmitSizedDeallocationFunction(*this, UnsizedDealloc);
} else
llvm_unreachable("no definition for emitted function");
@@ -909,8 +930,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return),
"missing_return", EmitCheckSourceLocation(FD->getLocation()),
None);
- } else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
+ } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+ EmitTrapCall(llvm::Intrinsic::trap);
+ }
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
}
@@ -949,8 +971,8 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
IgnoreCaseStmts = true;
// Scan subexpressions for verboten labels.
- for (Stmt::const_child_range I = S->children(); I; ++I)
- if (ContainsLabel(*I, IgnoreCaseStmts))
+ for (const Stmt *SubStmt : S->children())
+ if (ContainsLabel(SubStmt, IgnoreCaseStmts))
return true;
return false;
@@ -973,8 +995,8 @@ bool CodeGenFunction::containsBreak(const Stmt *S) {
return true;
// Scan subexpressions for verboten breaks.
- for (Stmt::const_child_range I = S->children(); I; ++I)
- if (containsBreak(*I))
+ for (const Stmt *SubStmt : S->children())
+ if (containsBreak(SubStmt))
return true;
return false;
@@ -1028,15 +1050,13 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Handle X && Y in a condition.
if (CondBOp->getOpcode() == BO_LAnd) {
- RegionCounter Cnt = getPGORegionCounter(CondBOp);
-
// If we have "1 && X", simplify the code. "0 && X" would have constant
// folded if the case was simple enough.
bool ConstantBool = false;
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
ConstantBool) {
// br(1 && X) -> br(X).
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(CondBOp);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
TrueCount);
}
@@ -1055,14 +1075,19 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true");
// The counter tells us how often we evaluate RHS, and all of TrueCount
// can be propagated to that branch.
- uint64_t RHSCount = Cnt.getCount();
+ uint64_t RHSCount = getProfileCount(CondBOp->getRHS());
ConditionalEvaluation eval(*this);
- EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount);
- EmitBlock(LHSTrue);
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount);
+ EmitBlock(LHSTrue);
+ }
+
+ incrementProfileCounter(CondBOp);
+ setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));
// Any temporaries created here are conditional.
- Cnt.beginRegion(Builder);
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount);
eval.end(*this);
@@ -1071,15 +1096,13 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
}
if (CondBOp->getOpcode() == BO_LOr) {
- RegionCounter Cnt = getPGORegionCounter(CondBOp);
-
// If we have "0 || X", simplify the code. "1 || X" would have constant
// folded if the case was simple enough.
bool ConstantBool = false;
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
!ConstantBool) {
// br(0 || X) -> br(X).
- Cnt.beginRegion(Builder);
+ incrementProfileCounter(CondBOp);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
TrueCount);
}
@@ -1099,15 +1122,21 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// We have the count for entry to the RHS and for the whole expression
// being true, so we can divy up True count between the short circuit and
// the RHS.
- uint64_t LHSCount = Cnt.getParentCount() - Cnt.getCount();
+ uint64_t LHSCount =
+ getCurrentProfileCount() - getProfileCount(CondBOp->getRHS());
uint64_t RHSCount = TrueCount - LHSCount;
ConditionalEvaluation eval(*this);
- EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount);
- EmitBlock(LHSFalse);
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount);
+ EmitBlock(LHSFalse);
+ }
+
+ incrementProfileCounter(CondBOp);
+ setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));
// Any temporaries created here are conditional.
- Cnt.beginRegion(Builder);
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount);
@@ -1121,7 +1150,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// br(!x, t, f) -> br(x, f, t)
if (CondUOp->getOpcode() == UO_LNot) {
// Negate the count.
- uint64_t FalseCount = PGO.getCurrentRegionCount() - TrueCount;
+ uint64_t FalseCount = getCurrentProfileCount() - TrueCount;
// Negate the condition and swap the destination blocks.
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock,
FalseCount);
@@ -1133,9 +1162,9 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
- RegionCounter Cnt = getPGORegionCounter(CondOp);
ConditionalEvaluation cond(*this);
- EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock, Cnt.getCount());
+ EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock,
+ getProfileCount(CondOp));
// When computing PGO branch weights, we only know the overall count for
// the true block. This code is essentially doing tail duplication of the
@@ -1144,15 +1173,19 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// the conditional operator.
uint64_t LHSScaledTrueCount = 0;
if (TrueCount) {
- double LHSRatio = Cnt.getCount() / (double) Cnt.getParentCount();
+ double LHSRatio =
+ getProfileCount(CondOp) / (double)getCurrentProfileCount();
LHSScaledTrueCount = TrueCount * LHSRatio;
}
cond.begin(*this);
EmitBlock(LHSBlock);
- Cnt.beginRegion(Builder);
- EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
- LHSScaledTrueCount);
+ incrementProfileCounter(CondOp);
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
+ LHSScaledTrueCount);
+ }
cond.end(*this);
cond.begin(*this);
@@ -1176,12 +1209,16 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Create branch weights based on the number of times we get here and the
// number of times the condition should be true.
- uint64_t CurrentCount = std::max(PGO.getCurrentRegionCount(), TrueCount);
- llvm::MDNode *Weights = PGO.createBranchWeights(TrueCount,
- CurrentCount - TrueCount);
+ uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
+ llvm::MDNode *Weights =
+ createProfileWeights(TrueCount, CurrentCount - TrueCount);
// Emit the code with the fully general case.
- llvm::Value *CondV = EvaluateExprAsBool(Cond);
+ llvm::Value *CondV;
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ CondV = EvaluateExprAsBool(Cond);
+ }
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights);
}
@@ -1231,7 +1268,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
/*volatile*/ false);
// Go to the next element.
- llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(cur, 1, "vla.next");
+ llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(),
+ cur, 1, "vla.next");
// Leave if that's the end of the VLA.
llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index 3a990d2..f2bc402 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -27,6 +27,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
@@ -96,8 +97,8 @@ enum TypeEvaluationKind {
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
- CodeGenFunction(const CodeGenFunction &) LLVM_DELETED_FUNCTION;
- void operator=(const CodeGenFunction &) LLVM_DELETED_FUNCTION;
+ CodeGenFunction(const CodeGenFunction &) = delete;
+ void operator=(const CodeGenFunction &) = delete;
friend class CGCXXABI;
public:
@@ -191,26 +192,25 @@ public:
CapturedRegionKind getKind() const { return Kind; }
- void setContextValue(llvm::Value *V) { ThisValue = V; }
+ virtual void setContextValue(llvm::Value *V) { ThisValue = V; }
// \brief Retrieve the value of the context parameter.
- llvm::Value *getContextValue() const { return ThisValue; }
+ virtual llvm::Value *getContextValue() const { return ThisValue; }
/// \brief Lookup the captured field decl for a variable.
- const FieldDecl *lookup(const VarDecl *VD) const {
+ virtual const FieldDecl *lookup(const VarDecl *VD) const {
return CaptureFields.lookup(VD);
}
- bool isCXXThisExprCaptured() const { return CXXThisFieldDecl != nullptr; }
- FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; }
+ bool isCXXThisExprCaptured() const { return getThisFieldDecl() != nullptr; }
+ virtual FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; }
static bool classof(const CGCapturedStmtInfo *) {
return true;
}
/// \brief Emit the captured statement body.
- virtual void EmitBody(CodeGenFunction &CGF, Stmt *S) {
- RegionCounter Cnt = CGF.getPGORegionCounter(S);
- Cnt.beginRegion(CGF.Builder);
+ virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) {
+ CGF.incrementProfileCounter(S);
CGF.EmitStmt(S);
}
@@ -233,6 +233,20 @@ public:
};
CGCapturedStmtInfo *CapturedStmtInfo;
+ /// \brief RAII for correct setting/restoring of CapturedStmtInfo.
+ class CGCapturedStmtRAII {
+ private:
+ CodeGenFunction &CGF;
+ CGCapturedStmtInfo *PrevCapturedStmtInfo;
+ public:
+ CGCapturedStmtRAII(CodeGenFunction &CGF,
+ CGCapturedStmtInfo *NewCapturedStmtInfo)
+ : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo) {
+ CGF.CapturedStmtInfo = NewCapturedStmtInfo;
+ }
+ ~CGCapturedStmtRAII() { CGF.CapturedStmtInfo = PrevCapturedStmtInfo; }
+ };
+
/// BoundsChecking - Emit run-time bounds checks. Higher values mean
/// potentially higher performance penalties.
unsigned char BoundsChecking;
@@ -262,6 +276,10 @@ public:
/// potentially set the return value.
bool SawAsmBlock;
+ /// True if the current function is an outlined SEH helper. This can be a
+ /// finally block or filter expression.
+ bool IsOutlinedSEHHelper;
+
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -274,16 +292,17 @@ public:
EHScopeStack EHStack;
llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
+ llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack;
/// Header for data within LifetimeExtendedCleanupStack.
struct LifetimeExtendedCleanupHeader {
/// The size of the following cleanup object.
- unsigned Size : 29;
+ unsigned Size;
/// The kind of cleanup to push: a value from the CleanupKind enumeration.
- unsigned Kind : 3;
+ CleanupKind Kind;
- size_t getSize() const { return size_t(Size); }
- CleanupKind getKind() const { return static_cast<CleanupKind>(Kind); }
+ size_t getSize() const { return Size; }
+ CleanupKind getKind() const { return Kind; }
};
/// i32s containing the indexes of the cleanup destinations.
@@ -305,6 +324,14 @@ public:
/// write the current selector value into this alloca.
llvm::AllocaInst *EHSelectorSlot;
+ /// 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;
+
+ /// Value returned by __exception_info intrinsic.
+ llvm::Value *SEHInfo = nullptr;
+
/// Emits a landing pad for the current EH stack.
llvm::BasicBlock *EmitLandingPad();
@@ -343,87 +370,32 @@ public:
void exit(CodeGenFunction &CGF);
};
- /// pushFullExprCleanup - Push a cleanup to be run at the end of the
- /// current full-expression. Safe against the possibility that
- /// we're currently inside a conditionally-evaluated expression.
- template <class T, class A0>
- void pushFullExprCleanup(CleanupKind kind, A0 a0) {
- // If we're not in a conditional branch, or if none of the
- // arguments requires saving, then use the unconditional cleanup.
- if (!isInConditionalBranch())
- return EHStack.pushCleanup<T>(kind, a0);
-
- typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
-
- typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType;
- EHStack.pushCleanup<CleanupType>(kind, a0_saved);
- initFullExprCleanup();
- }
+ /// Returns true inside SEH __try blocks.
+ bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
/// pushFullExprCleanup - Push a cleanup to be run at the end of the
/// current full-expression. Safe against the possibility that
/// we're currently inside a conditionally-evaluated expression.
- template <class T, class A0, class A1>
- void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) {
+ template <class T, class... As>
+ void pushFullExprCleanup(CleanupKind kind, As... A) {
// If we're not in a conditional branch, or if none of the
// arguments requires saving, then use the unconditional cleanup.
if (!isInConditionalBranch())
- return EHStack.pushCleanup<T>(kind, a0, a1);
-
- typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
- typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
-
- typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType;
- EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved);
- initFullExprCleanup();
- }
+ return EHStack.pushCleanup<T>(kind, A...);
- /// pushFullExprCleanup - Push a cleanup to be run at the end of the
- /// current full-expression. Safe against the possibility that
- /// we're currently inside a conditionally-evaluated expression.
- template <class T, class A0, class A1, class A2>
- void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2) {
- // If we're not in a conditional branch, or if none of the
- // arguments requires saving, then use the unconditional cleanup.
- if (!isInConditionalBranch()) {
- return EHStack.pushCleanup<T>(kind, a0, a1, a2);
- }
-
- typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
- typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
- typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2);
-
- typedef EHScopeStack::ConditionalCleanup3<T, A0, A1, A2> CleanupType;
- EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved, a2_saved);
- initFullExprCleanup();
- }
+ // Stash values in a tuple so we can guarantee the order of saves.
+ typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple;
+ SavedTuple Saved{saveValueInCond(A)...};
- /// pushFullExprCleanup - Push a cleanup to be run at the end of the
- /// current full-expression. Safe against the possibility that
- /// we're currently inside a conditionally-evaluated expression.
- template <class T, class A0, class A1, class A2, class A3>
- void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2, A3 a3) {
- // If we're not in a conditional branch, or if none of the
- // arguments requires saving, then use the unconditional cleanup.
- if (!isInConditionalBranch()) {
- return EHStack.pushCleanup<T>(kind, a0, a1, a2, a3);
- }
-
- typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
- typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
- typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2);
- typename DominatingValue<A3>::saved_type a3_saved = saveValueInCond(a3);
-
- typedef EHScopeStack::ConditionalCleanup4<T, A0, A1, A2, A3> CleanupType;
- EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved,
- a2_saved, a3_saved);
+ typedef EHScopeStack::ConditionalCleanup<T, As...> CleanupType;
+ EHStack.pushCleanupTuple<CleanupType>(kind, Saved);
initFullExprCleanup();
}
/// \brief Queue a cleanup to be pushed after finishing the current
/// full-expression.
- template <class T, class A0, class A1, class A2, class A3>
- void pushCleanupAfterFullExpr(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ template <class T, class... As>
+ void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) {
assert(!isInConditionalBranch() && "can't defer conditional cleanup");
LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind };
@@ -432,9 +404,11 @@ public:
LifetimeExtendedCleanupStack.resize(
LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size);
+ static_assert(sizeof(Header) % llvm::AlignOf<T>::Alignment == 0,
+ "Cleanup will be allocated on misaligned address");
char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
new (Buffer) LifetimeExtendedCleanupHeader(Header);
- new (Buffer + sizeof(Header)) T(a0, a1, a2, a3);
+ new (Buffer + sizeof(Header)) T(A...);
}
/// Set up the last cleaup that was pushed as a conditional
@@ -488,8 +462,8 @@ public:
bool PerformCleanup;
private:
- RunCleanupsScope(const RunCleanupsScope &) LLVM_DELETED_FUNCTION;
- void operator=(const RunCleanupsScope &) LLVM_DELETED_FUNCTION;
+ RunCleanupsScope(const RunCleanupsScope &) = delete;
+ void operator=(const RunCleanupsScope &) = delete;
protected:
CodeGenFunction& CGF;
@@ -537,8 +511,8 @@ public:
SmallVector<const LabelDecl*, 4> Labels;
LexicalScope *ParentScope;
- LexicalScope(const LexicalScope &) LLVM_DELETED_FUNCTION;
- void operator=(const LexicalScope &) LLVM_DELETED_FUNCTION;
+ LexicalScope(const LexicalScope &) = delete;
+ void operator=(const LexicalScope &) = delete;
public:
/// \brief Enter a new cleanup scope.
@@ -562,7 +536,10 @@ public:
// If we should perform a cleanup, force them now. Note that
// this ends the cleanup scope before rescoping any labels.
- if (PerformCleanup) ForceCleanup();
+ if (PerformCleanup) {
+ ApplyDebugLocation DL(CGF, Range.getEnd());
+ ForceCleanup();
+ }
}
/// \brief Force the emission of cleanups now, instead of waiting
@@ -587,8 +564,8 @@ public:
VarDeclMapTy SavedPrivates;
private:
- OMPPrivateScope(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
- void operator=(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
+ OMPPrivateScope(const OMPPrivateScope &) = delete;
+ void operator=(const OMPPrivateScope &) = delete;
public:
/// \brief Enter a new OpenMP private scope.
@@ -637,7 +614,10 @@ public:
}
/// \brief Exit scope - all the mapped variables are restored.
- ~OMPPrivateScope() { ForceCleanup(); }
+ ~OMPPrivateScope() {
+ if (PerformCleanup)
+ ForceCleanup();
+ }
};
/// \brief Takes the old cleanup stack size and emits the cleanup blocks
@@ -881,7 +861,8 @@ public:
/// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
/// number that holds the value.
- unsigned getByRefValueLLVMField(const ValueDecl *VD) const;
+ std::pair<llvm::Type *, unsigned>
+ getByRefValueLLVMField(const ValueDecl *VD) const;
/// BuildBlockByrefAddress - Computes address location of the
/// variable which is declared as __block.
@@ -906,6 +887,10 @@ private:
typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
+ /// Track escaped local variables with auto storage. Used during SEH
+ /// 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.
llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
@@ -922,12 +907,39 @@ private:
CodeGenPGO PGO;
+ /// Calculate branch weights appropriate for PGO data
+ llvm::MDNode *createProfileWeights(uint64_t TrueCount, uint64_t FalseCount);
+ llvm::MDNode *createProfileWeights(ArrayRef<uint64_t> Weights);
+ llvm::MDNode *createProfileWeightsForLoop(const Stmt *Cond,
+ uint64_t LoopCount);
+
public:
- /// Get a counter for instrumentation of the region associated with the given
- /// statement.
- RegionCounter getPGORegionCounter(const Stmt *S) {
- return RegionCounter(PGO, S);
+ /// Increment the profiler's counter for the given statement.
+ void incrementProfileCounter(const Stmt *S) {
+ if (CGM.getCodeGenOpts().ProfileInstrGenerate)
+ PGO.emitCounterIncrement(Builder, S);
+ PGO.setCurrentStmt(S);
+ }
+
+ /// Get the profiler's count for the given statement.
+ uint64_t getProfileCount(const Stmt *S) {
+ Optional<uint64_t> Count = PGO.getStmtCount(S);
+ if (!Count.hasValue())
+ return 0;
+ return *Count;
+ }
+
+ /// Set the profiler's current count.
+ void setCurrentProfileCount(uint64_t Count) {
+ PGO.setCurrentRegionCount(Count);
}
+
+ /// Get the profiler's current count. This is generally the count for the most
+ /// recently incremented counter.
+ uint64_t getCurrentProfileCount() {
+ return PGO.getCurrentRegionCount();
+ }
+
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
@@ -1097,6 +1109,11 @@ public:
return getInvokeDestImpl();
}
+ bool currentFunctionUsesSEHTry() const {
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
+ return FD && FD->usesSEHTry();
+ }
+
const TargetInfo &getTarget() const { return Target; }
llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); }
@@ -1248,7 +1265,7 @@ public:
void EmitDestructorBody(FunctionArgList &Args);
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args);
void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body);
- void EmitBlockWithFallThrough(llvm::BasicBlock *BB, RegionCounter &Cnt);
+ void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S);
void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
CallArgList &CallArgs);
@@ -1258,15 +1275,18 @@ public:
void EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD);
void EmitAsanPrologueOrEpilogue(bool Prologue);
- /// EmitReturnBlock - Emit the unified return block, trying to avoid its
- /// emission when possible.
+ /// \brief Emit the unified return block, trying to avoid its emission when
+ /// possible.
+ /// \return The debug location of the user written return statement if the
+ /// return block is is avoided.
llvm::DebugLoc EmitReturnBlock();
/// FinishFunction - Complete IR generation of the current function. It is
/// legal to call this function even if there is no current insertion point.
void FinishFunction(SourceLocation EndLoc=SourceLocation());
- void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo);
+ void StartThunk(llvm::Function *Fn, GlobalDecl GD,
+ const CGFunctionInfo &FnInfo);
void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk);
@@ -1274,12 +1294,13 @@ 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);
- void GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
- GlobalDecl GD, const ThunkInfo &Thunk);
+ llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
+ const CGFunctionInfo &FnInfo,
+ GlobalDecl GD, const ThunkInfo &Thunk);
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
FunctionArgList &Args);
@@ -1309,6 +1330,29 @@ public:
/// to by This.
llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
+ enum CFITypeCheckKind {
+ CFITCK_VCall,
+ CFITCK_NVCall,
+ CFITCK_DerivedCast,
+ CFITCK_UnrelatedCast,
+ };
+
+ /// \brief Derived is the presumed address of an object of type T after a
+ /// cast. If T is a polymorphic class type, emit a check that the virtual
+ /// table for Derived belongs to a class derived from T.
+ void EmitVTablePtrCheckForCast(QualType T, llvm::Value *Derived,
+ bool MayBeNull, CFITypeCheckKind TCK,
+ SourceLocation Loc);
+
+ /// EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.
+ /// If vptr CFI is enabled, emit a check that VTable is valid.
+ void EmitVTablePtrCheckForCall(const CXXMethodDecl *MD, llvm::Value *VTable,
+ CFITypeCheckKind TCK, SourceLocation Loc);
+
+ /// EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for
+ /// RD using llvm.bitset.test.
+ void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable,
+ CFITypeCheckKind TCK, SourceLocation Loc);
/// CanDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
/// expr can be devirtualized.
@@ -1527,6 +1571,8 @@ public:
void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
Qualifiers Quals, bool IsInitializer);
+ void EmitAnyExprToExn(const Expr *E, llvm::Value *Addr);
+
/// EmitExprAsInit - Emits the code necessary to initialize a
/// location in memory with the given initializer.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue,
@@ -1552,6 +1598,15 @@ public:
true);
}
+ void EmitAggregateCopyCtor(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ QualType DestTy, QualType SrcTy) {
+ CharUnits DestTypeAlign = getContext().getTypeAlignInChars(DestTy);
+ CharUnits SrcTypeAlign = getContext().getTypeAlignInChars(SrcTy);
+ EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false,
+ std::min(DestTypeAlign, SrcTypeAlign),
+ /*IsAssignment=*/false);
+ }
+
/// EmitAggregateCopy - Emit an aggregate copy.
///
/// \param isVolatile - True iff either the source or the destination is
@@ -1723,12 +1778,16 @@ public:
llvm::Value *This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
- llvm::Value *NewPtr, llvm::Value *NumElements,
+ llvm::Type *ElementTy, llvm::Value *NewPtr,
+ llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
llvm::Value *Ptr);
+ llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -1889,8 +1948,8 @@ public:
llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
if (!IsByRef) return Address;
- return CGF.Builder.CreateStructGEP(Address,
- CGF.getByRefValueLLVMField(Variable),
+ auto F = CGF.getByRefValueLLVMField(Variable);
+ return CGF.Builder.CreateStructGEP(F.first, Address, F.second,
Variable->getNameAsString());
}
};
@@ -1988,6 +2047,40 @@ public:
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
+ void EnterSEHTryStmt(const SEHTryStmt &S);
+ void ExitSEHTryStmt(const SEHTryStmt &S);
+
+ void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
+ const Stmt *OutlinedStmt);
+
+ llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
+ const SEHExceptStmt &Except);
+
+ llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally);
+
+ 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.localrecover. Insert the localrecover result into the LocalDeclMap.
+ void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
+ 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);
@@ -1997,13 +2090,107 @@ public:
llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);
llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
- void EmitOMPAggregateAssign(LValue OriginalAddr, llvm::Value *PrivateAddr,
- const Expr *AssignExpr, QualType Type,
- const VarDecl *VDInit);
- void EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
+ /// \brief Perform element by element copying of arrays with type \a
+ /// OriginalType from \a SrcAddr to \a DestAddr using copying procedure
+ /// generated by \a CopyGen.
+ ///
+ /// \param DestAddr Address of the destination array.
+ /// \param SrcAddr Address of the source array.
+ /// \param OriginalType Type of destination and source arrays.
+ /// \param CopyGen Copying procedure that copies value of single array element
+ /// to another single array element.
+ void EmitOMPAggregateAssign(
+ llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen);
+ /// \brief Emit proper copying of data from one variable to another.
+ ///
+ /// \param OriginalType Original type of the copied variables.
+ /// \param DestAddr Destination address.
+ /// \param SrcAddr Source address.
+ /// \param DestVD Destination variable used in \a CopyExpr (for arrays, has
+ /// type of the base array element).
+ /// \param SrcVD Source variable used in \a CopyExpr (for arrays, has type of
+ /// the base array element).
+ /// \param Copy Actual copygin expression for copying data from \a SrcVD to \a
+ /// DestVD.
+ void EmitOMPCopy(CodeGenFunction &CGF, QualType OriginalType,
+ llvm::Value *DestAddr, llvm::Value *SrcAddr,
+ const VarDecl *DestVD, const VarDecl *SrcVD,
+ const Expr *Copy);
+ /// \brief Emit atomic update code for constructs: \a X = \a X \a BO \a E or
+ /// \a X = \a E \a BO \a E.
+ ///
+ /// \param X Value to be updated.
+ /// \param E Update value.
+ /// \param BO Binary operation for update operation.
+ /// \param IsXLHSInRHSPart true if \a X is LHS in RHS part of the update
+ /// expression, false otherwise.
+ /// \param AO Atomic ordering of the generated atomic instructions.
+ /// \param CommonGen Code generator for complex expressions that cannot be
+ /// expressed through atomicrmw instruction.
+ /// \returns <true, OldAtomicValue> if simple 'atomicrmw' instruction was
+ /// generated, <false, RValue::get(nullptr)> otherwise.
+ std::pair<bool, RValue> EmitOMPAtomicSimpleUpdateExpr(
+ LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
+ llvm::AtomicOrdering AO, SourceLocation Loc,
+ const llvm::function_ref<RValue(RValue)> &CommonGen);
+ bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
+ /// \brief Emit code for copyin clause in \a D directive. The next code is
+ /// generated at the start of outlined functions for directives:
+ /// \code
+ /// threadprivate_var1 = master_threadprivate_var1;
+ /// operator=(threadprivate_var2, master_threadprivate_var2);
+ /// ...
+ /// __kmpc_barrier(&loc, global_tid);
+ /// \endcode
+ ///
+ /// \param D OpenMP directive possibly with 'copyin' clause(s).
+ /// \returns true if at least one copyin variable is found, false otherwise.
+ bool EmitOMPCopyinClause(const OMPExecutableDirective &D);
+ /// \brief Emit initial code for lastprivate variables. If some variable is
+ /// not also firstprivate, then the default initialization is used. Otherwise
+ /// initialization of this variable is performed by EmitOMPFirstprivateClause
+ /// method.
+ ///
+ /// \param D Directive that may have 'lastprivate' directives.
+ /// \param PrivateScope Private scope for capturing lastprivate variables for
+ /// proper codegen in internal captured statement.
+ ///
+ /// \returns true if there is at least one lastprivate variable, false
+ /// otherwise.
+ bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope);
+ /// \brief Emit final copying of lastprivate values to original variables at
+ /// the end of the worksharing or simd directive.
+ ///
+ /// \param D Directive that has at least one 'lastprivate' directives.
+ /// \param IsLastIterCond Boolean condition that must be set to 'i1 true' if
+ /// it is the last iteration of the loop code in associated directive, or to
+ /// 'i1 false' otherwise. If this item is nullptr, no final check is required.
+ void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D,
+ llvm::Value *IsLastIterCond = nullptr);
+ /// \brief Emit initial code for reduction variables. Creates reduction copies
+ /// and initializes them with the values according to OpenMP standard.
+ ///
+ /// \param D Directive (possibly) with the 'reduction' clause.
+ /// \param PrivateScope Private scope for capturing reduction variables for
+ /// proper codegen in internal captured statement.
+ ///
+ void EmitOMPReductionClauseInit(const OMPExecutableDirective &D,
+ OMPPrivateScope &PrivateScope);
+ /// \brief Emit final update of reduction values to original variables at
+ /// the end of the directive.
+ ///
+ /// \param D Directive that has at least one 'reduction' directives.
+ void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D);
+ /// \brief Emit initial code for linear variables. Creates private copies
+ /// and initializes them with the values according to OpenMP standard.
+ ///
+ /// \param D Directive (possibly) with the 'linear' clause.
+ void EmitOMPLinearClauseInit(const OMPLoopDirective &D);
void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S);
@@ -2021,21 +2208,51 @@ public:
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S);
void EmitOMPBarrierDirective(const OMPBarrierDirective &S);
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S);
+ void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S);
void EmitOMPFlushDirective(const OMPFlushDirective &S);
void EmitOMPOrderedDirective(const OMPOrderedDirective &S);
void EmitOMPAtomicDirective(const OMPAtomicDirective &S);
void EmitOMPTargetDirective(const OMPTargetDirective &S);
void EmitOMPTeamsDirective(const OMPTeamsDirective &S);
+ void
+ EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S);
+ void EmitOMPCancelDirective(const OMPCancelDirective &S);
+
+ /// \brief Emit inner loop of the worksharing/simd construct.
+ ///
+ /// \param S Directive, for which the inner loop must be emitted.
+ /// \param RequiresCleanup true, if directive has some associated private
+ /// variables.
+ /// \param LoopCond Bollean condition for loop continuation.
+ /// \param IncExpr Increment expression for loop control variable.
+ /// \param BodyGen Generator for the inner body of the inner loop.
+ /// \param PostIncGen Genrator for post-increment code (required for ordered
+ /// loop directvies).
+ void EmitOMPInnerLoop(
+ const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
+ const Expr *IncExpr,
+ const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
+ const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen);
+
+ JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind);
private:
/// Helpers for the OpenMP loop directives.
- void EmitOMPLoopBody(const OMPLoopDirective &Directive,
- bool SeparateIter = false);
- void EmitOMPInnerLoop(const OMPLoopDirective &S, OMPPrivateScope &LoopScope,
- bool SeparateIter = false);
- void EmitOMPSimdFinal(const OMPLoopDirective &S);
- void EmitOMPWorksharingLoop(const OMPLoopDirective &S);
+ void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
+ void EmitOMPSimdInit(const OMPLoopDirective &D);
+ void EmitOMPSimdFinal(const OMPLoopDirective &D);
+ /// \brief Emit code for the worksharing loop-based directive.
+ /// \return true, if this construct has any lastprivate clause, false -
+ /// otherwise.
+ bool EmitOMPWorksharingLoop(const OMPLoopDirective &S);
+ void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
+ const OMPLoopDirective &S,
+ OMPPrivateScope &LoopScope, bool Ordered,
+ llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
+ llvm::Value *IL, llvm::Value *Chunk);
+ /// \brief Emit code for sections directive.
+ OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S);
public:
@@ -2085,17 +2302,31 @@ public:
void EmitAtomicInit(Expr *E, LValue lvalue);
+ bool LValueIsSuitableForInlineAtomic(LValue Src);
+ bool typeIsSuitableForInlineAtomic(QualType Ty, bool IsVolatile) const;
+
+ RValue EmitAtomicLoad(LValue LV, SourceLocation SL,
+ AggValueSlot Slot = AggValueSlot::ignored());
+
RValue EmitAtomicLoad(LValue lvalue, SourceLocation loc,
+ llvm::AtomicOrdering AO, bool IsVolatile = false,
AggValueSlot slot = AggValueSlot::ignored());
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit);
- std::pair<RValue, RValue> EmitAtomicCompareExchange(
+ void EmitAtomicStore(RValue rvalue, LValue lvalue, llvm::AtomicOrdering AO,
+ bool IsVolatile, bool isInit);
+
+ std::pair<RValue, llvm::Value *> EmitAtomicCompareExchange(
LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,
llvm::AtomicOrdering Success = llvm::SequentiallyConsistent,
llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent,
bool IsWeak = false, AggValueSlot Slot = AggValueSlot::ignored());
+ void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO,
+ const llvm::function_ref<RValue(RValue)> &UpdateOp,
+ bool IsVolatile);
+
/// EmitToMemory - Change a scalar value from its value
/// representation to its in-memory representation.
llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty);
@@ -2163,8 +2394,8 @@ public:
/// Emit an l-value for an assignment (simple or compound) of complex type.
LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
- LValue EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
- llvm::Value *&Result);
+ LValue EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result);
// Note: only available for agg return types
LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
@@ -2208,7 +2439,7 @@ public:
return ConstantEmission(C, false);
}
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return ValueAndIsReference.getOpaqueValue() != nullptr;
}
@@ -2384,19 +2615,14 @@ public:
// Helper functions for EmitAArch64BuiltinExpr.
llvm::Value *vectorWrapScalar8(llvm::Value *Op);
llvm::Value *vectorWrapScalar16(llvm::Value *Op);
- llvm::Value *emitVectorWrappedScalar8Intrinsic(
- unsigned Int, SmallVectorImpl<llvm::Value *> &Ops, const char *Name);
- llvm::Value *emitVectorWrappedScalar16Intrinsic(
- unsigned Int, SmallVectorImpl<llvm::Value *> &Ops, const char *Name);
llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
- llvm::Value *EmitNeon64Call(llvm::Function *F,
- llvm::SmallVectorImpl<llvm::Value *> &O,
- const char *name);
llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
- llvm::Value *EmitR600BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
@@ -2655,7 +2881,7 @@ public:
/// \brief Create a basic block that will call a handler function in a
/// sanitizer runtime with the provided arguments, and create a conditional
/// branch to it.
- void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerKind>> Checked,
+ void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs);
@@ -2663,6 +2889,15 @@ public:
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked);
+ /// \brief Emit a call to trap or debugtrap and attach function attribute
+ /// "trap-func-name" if specified.
+ llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
+
+ /// \brief Create a check for a function parameter that may potentially be
+ /// declared as non-null.
+ void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc,
+ const FunctionDecl *FD, unsigned ParmNum);
+
/// EmitCallArg - Emit a single call argument.
void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType);
@@ -2708,31 +2943,58 @@ 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,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
const FunctionDecl *CalleeDecl = nullptr,
- unsigned ParamsToSkip = 0, bool ForceColumnInfo = false) {
+ unsigned ParamsToSkip = 0) {
SmallVector<QualType, 16> ArgTypes;
CallExpr::const_arg_iterator Arg = ArgBeg;
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);
}
}
@@ -2747,15 +3009,14 @@ public:
for (; Arg != ArgEnd; ++Arg)
ArgTypes.push_back(getVarArgType(*Arg));
- EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip,
- ForceColumnInfo);
+ EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip);
}
void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
const FunctionDecl *CalleeDecl = nullptr,
- unsigned ParamsToSkip = 0, bool ForceColumnInfo = false);
+ unsigned ParamsToSkip = 0);
private:
QualType getVarArgType(const Expr *Arg);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index d653130..a179ad4 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -74,16 +74,19 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
llvm_unreachable("invalid C++ ABI kind");
}
-CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
- llvm::Module &M, const llvm::DataLayout &TD,
+CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
+ const PreprocessorOptions &PPO,
+ const CodeGenOptions &CGO, llvm::Module &M,
+ const llvm::DataLayout &TD,
DiagnosticsEngine &diags,
CoverageSourceInfo *CoverageInfo)
- : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
- Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
- ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(nullptr),
- TheTargetCodeGenInfo(nullptr), Types(*this), VTables(*this),
- ObjCRuntime(nullptr), OpenCLRuntime(nullptr), OpenMPRuntime(nullptr),
- CUDARuntime(nullptr), DebugInfo(nullptr), ARCData(nullptr),
+ : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO),
+ PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
+ TheDataLayout(TD), Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
+ VMContext(M.getContext()), TBAA(nullptr), TheTargetCodeGenInfo(nullptr),
+ Types(*this), VTables(*this), ObjCRuntime(nullptr),
+ OpenCLRuntime(nullptr), OpenMPRuntime(nullptr), CUDARuntime(nullptr),
+ DebugInfo(nullptr), ARCData(nullptr),
NoObjCARCExceptionsMetadata(nullptr), RRData(nullptr), PGOReader(nullptr),
CFConstantStringClassRef(nullptr), ConstantStringClassRef(nullptr),
NSConstantStringType(nullptr), NSConcreteGlobalBlock(nullptr),
@@ -141,12 +144,15 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
RRData = new RREntrypoints();
if (!CodeGenOpts.InstrProfileInput.empty()) {
- if (std::error_code EC = llvm::IndexedInstrProfReader::create(
- CodeGenOpts.InstrProfileInput, PGOReader)) {
+ auto ReaderOrErr =
+ llvm::IndexedInstrProfReader::create(CodeGenOpts.InstrProfileInput);
+ if (std::error_code EC = ReaderOrErr.getError()) {
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "Could not read profile: %0");
- getDiags().Report(DiagID) << EC.message();
- }
+ "Could not read profile %0: %1");
+ getDiags().Report(DiagID) << CodeGenOpts.InstrProfileInput
+ << EC.message();
+ } else
+ PGOReader = std::move(ReaderOrErr.get());
}
// If coverage mapping generation is enabled, create the
@@ -203,11 +209,9 @@ void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) {
}
void CodeGenModule::applyReplacements() {
- for (ReplacementsTy::iterator I = Replacements.begin(),
- E = Replacements.end();
- I != E; ++I) {
- StringRef MangledName = I->first();
- llvm::Constant *Replacement = I->second;
+ for (auto &I : Replacements) {
+ StringRef MangledName = I.first();
+ llvm::Constant *Replacement = I.second;
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (!Entry)
continue;
@@ -259,9 +263,7 @@ void CodeGenModule::checkAliases() {
// and aliases during codegen.
bool Error = false;
DiagnosticsEngine &Diags = getDiags();
- for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
- E = Aliases.end(); I != E; ++I) {
- const GlobalDecl &GD = *I;
+ for (const GlobalDecl &GD : Aliases) {
const auto *D = cast<ValueDecl>(GD.getDecl());
const AliasAttr *AA = D->getAttr<AliasAttr>();
StringRef MangledName = getMangledName(GD);
@@ -308,9 +310,7 @@ void CodeGenModule::checkAliases() {
if (!Error)
return;
- for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
- E = Aliases.end(); I != E; ++I) {
- const GlobalDecl &GD = *I;
+ for (const GlobalDecl &GD : Aliases) {
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
auto *Alias = cast<llvm::GlobalAlias>(Entry);
@@ -321,6 +321,8 @@ void CodeGenModule::checkAliases() {
void CodeGenModule::clear() {
DeferredDeclsToEmit.clear();
+ if (OpenMPRuntime)
+ OpenMPRuntime->clear();
}
void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
@@ -346,6 +348,13 @@ void CodeGenModule::Release() {
if (ObjCRuntime)
if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
+ if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice &&
+ CUDARuntime) {
+ if (llvm::Function *CudaCtorFunction = CUDARuntime->makeModuleCtorFunction())
+ AddGlobalCtor(CudaCtorFunction);
+ if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction())
+ AddGlobalDtor(CudaDtorFunction);
+ }
if (PGOReader && PGOStats.hasDiagnostics())
PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
EmitCtorList(GlobalCtors, "llvm.global_ctors");
@@ -626,15 +635,14 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, nullptr);
// Construct the constructor and destructor arrays.
- SmallVector<llvm::Constant*, 8> Ctors;
- for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+ SmallVector<llvm::Constant *, 8> Ctors;
+ for (const auto &I : Fns) {
llvm::Constant *S[] = {
- llvm::ConstantInt::get(Int32Ty, I->Priority, false),
- llvm::ConstantExpr::getBitCast(I->Initializer, CtorPFTy),
- (I->AssociatedData
- ? llvm::ConstantExpr::getBitCast(I->AssociatedData, VoidPtrTy)
- : llvm::Constant::getNullValue(VoidPtrTy))
- };
+ llvm::ConstantInt::get(Int32Ty, I.Priority, false),
+ llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy),
+ (I.AssociatedData
+ ? llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)
+ : llvm::Constant::getNullValue(VoidPtrTy))};
Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
}
@@ -665,6 +673,25 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false);
}
+void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+
+ if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) {
+ if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
+ // Don't dllexport/import destructor thunks.
+ F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ return;
+ }
+ }
+
+ if (FD->hasAttr<DLLImportAttr>())
+ F->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ else if (FD->hasAttr<DLLExportAttr>())
+ F->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
+ else
+ F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
+}
+
void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::Function *F) {
setNonAliasAttributes(D, F);
@@ -741,23 +768,6 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
B.addAttribute(llvm::Attribute::StackProtectReq);
- // Add sanitizer attributes if function is not blacklisted.
- if (!isInSanitizerBlacklist(F, D->getLocation())) {
- // When AddressSanitizer is enabled, set SanitizeAddress attribute
- // unless __attribute__((no_sanitize_address)) is used.
- if (LangOpts.Sanitize.has(SanitizerKind::Address) &&
- !D->hasAttr<NoSanitizeAddressAttr>())
- B.addAttribute(llvm::Attribute::SanitizeAddress);
- // Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
- if (LangOpts.Sanitize.has(SanitizerKind::Thread) &&
- !D->hasAttr<NoSanitizeThreadAttr>())
- B.addAttribute(llvm::Attribute::SanitizeThread);
- // Same for MemorySanitizer and __attribute__((no_sanitize_memory))
- if (LangOpts.Sanitize.has(SanitizerKind::Memory) &&
- !D->hasAttr<NoSanitizeMemoryAttr>())
- B.addAttribute(llvm::Attribute::SanitizeMemory);
- }
-
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(), llvm::AttributeSet::FunctionIndex, B));
@@ -823,7 +833,7 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
GO->setSection(SA->getName());
- getTargetCodeGenInfo().SetTargetAttributes(D, GO, *this);
+ getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
}
void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
@@ -865,11 +875,10 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
bool IsIncompleteFunction,
bool IsThunk) {
- if (unsigned IID = F->getIntrinsicID()) {
+ if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) {
// If this is an intrinsic function, set the function's attributes
// to the intrinsic's attributes.
- F->setAttributes(llvm::Intrinsic::getAttributes(getLLVMContext(),
- (llvm::Intrinsic::ID)IID));
+ F->setAttributes(llvm::Intrinsic::getAttributes(getLLVMContext(), IID));
return;
}
@@ -896,13 +905,6 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
setLinkageAndVisibilityForGV(F, FD);
- if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) {
- if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
- // Don't dllexport/import destructor thunks.
- F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- }
- }
-
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
F->setSection(SA->getName());
@@ -916,13 +918,13 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
assert(!GV->isDeclaration() &&
"Only globals with definition can force usage.");
- LLVMUsed.push_back(GV);
+ LLVMUsed.emplace_back(GV);
}
void CodeGenModule::addCompilerUsedGlobal(llvm::GlobalValue *GV) {
assert(!GV->isDeclaration() &&
"Only globals with definition can force usage.");
- LLVMCompilerUsed.push_back(GV);
+ LLVMCompilerUsed.emplace_back(GV);
}
static void emitUsed(CodeGenModule &CGM, StringRef Name,
@@ -1024,12 +1026,9 @@ void CodeGenModule::EmitModuleLinkOptions() {
SmallVector<clang::Module *, 16> Stack;
// Seed the stack with imported modules.
- for (llvm::SetVector<clang::Module *>::iterator M = ImportedModules.begin(),
- MEnd = ImportedModules.end();
- M != MEnd; ++M) {
- if (Visited.insert(*M).second)
- Stack.push_back(*M);
- }
+ for (Module *M : ImportedModules)
+ if (Visited.insert(M).second)
+ Stack.push_back(M);
// Find all of the modules to import, making a little effort to prune
// non-leaf modules.
@@ -1065,12 +1064,9 @@ void CodeGenModule::EmitModuleLinkOptions() {
// to linker options inserted by things like #pragma comment().
SmallVector<llvm::Metadata *, 16> MetadataArgs;
Visited.clear();
- for (llvm::SetVector<clang::Module *>::iterator M = LinkModules.begin(),
- MEnd = LinkModules.end();
- M != MEnd; ++M) {
- if (Visited.insert(*M).second)
- addLinkOptionsPostorder(*this, *M, MetadataArgs, Visited);
- }
+ for (Module *M : LinkModules)
+ if (Visited.insert(M).second)
+ addLinkOptionsPostorder(*this, M, MetadataArgs, Visited);
std::reverse(MetadataArgs.begin(), MetadataArgs.end());
LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());
@@ -1085,29 +1081,33 @@ void CodeGenModule::EmitDeferred() {
// previously unused static decl may become used during the generation of code
// for a static function, iterate until no changes are made.
- while (true) {
- if (!DeferredVTables.empty()) {
- EmitDeferredVTables();
+ if (!DeferredVTables.empty()) {
+ EmitDeferredVTables();
- // Emitting a v-table doesn't directly cause more v-tables to
- // become deferred, although it can cause functions to be
- // emitted that then need those v-tables.
- assert(DeferredVTables.empty());
- }
+ // Emitting a v-table doesn't directly cause more v-tables to
+ // become deferred, although it can cause functions to be
+ // emitted that then need those v-tables.
+ assert(DeferredVTables.empty());
+ }
+
+ // Stop if we're out of both deferred v-tables and deferred declarations.
+ if (DeferredDeclsToEmit.empty())
+ return;
- // Stop if we're out of both deferred v-tables and deferred declarations.
- if (DeferredDeclsToEmit.empty()) break;
+ // Grab the list of decls to emit. If EmitGlobalDefinition schedules more
+ // work, it will not interfere with this.
+ std::vector<DeferredGlobal> CurDeclsToEmit;
+ CurDeclsToEmit.swap(DeferredDeclsToEmit);
- DeferredGlobal &G = DeferredDeclsToEmit.back();
+ for (DeferredGlobal &G : CurDeclsToEmit) {
GlobalDecl D = G.GD;
llvm::GlobalValue *GV = G.GV;
- DeferredDeclsToEmit.pop_back();
+ G.GV = nullptr;
assert(!GV || GV == GetGlobalValue(getMangledName(D)));
if (!GV)
GV = GetGlobalValue(getMangledName(D));
-
// Check to see if we've already emitted this. This is necessary
// for a couple of reasons: first, decls can end up in the
// deferred-decls queue multiple times, and second, decls can end
@@ -1119,6 +1119,14 @@ void CodeGenModule::EmitDeferred() {
// Otherwise, emit the definition and move on to the next one.
EmitGlobalDefinition(D, GV);
+
+ // If we found out that we need to emit more decls, do that recursively.
+ // This has the advantage that the decls are emitted in a DFS and related
+ // ones are close together, which is convenient for testing.
+ if (!DeferredVTables.empty() || !DeferredDeclsToEmit.empty()) {
+ EmitDeferred();
+ assert(DeferredVTables.empty() && DeferredDeclsToEmit.empty());
+ }
}
}
@@ -1214,8 +1222,9 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
SourceLocation Loc, QualType Ty,
StringRef Category) const {
- // For now globals can be blacklisted only in ASan.
- if (!LangOpts.Sanitize.has(SanitizerKind::Address))
+ // For now globals can be blacklisted only in ASan and KASan.
+ if (!LangOpts.Sanitize.hasOneOf(
+ SanitizerKind::Address | SanitizerKind::KernelAddress))
return false;
const auto &SanitizerBL = getContext().getSanitizerBlacklist();
if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category))
@@ -1253,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;
}
@@ -1275,6 +1289,8 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
auto *GV = new llvm::GlobalVariable(
getModule(), Init->getType(),
/*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+ if (supportsCOMDAT())
+ GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
return GV;
}
@@ -1322,7 +1338,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If this is CUDA, be selective about which declarations we emit.
if (LangOpts.CUDA) {
- if (CodeGenOpts.CUDAIsDevice) {
+ if (LangOpts.CUDAIsDevice) {
if (!Global->hasAttr<CUDADeviceAttr>() &&
!Global->hasAttr<CUDAGlobalAttr>() &&
!Global->hasAttr<CUDAConstantAttr>() &&
@@ -1417,7 +1433,7 @@ namespace {
return false;
}
unsigned BuiltinID = FD->getBuiltinID();
- if (!BuiltinID)
+ if (!BuiltinID || !BI.isLibFunction(BuiltinID))
return true;
StringRef BuiltinName = BI.GetName(BuiltinID);
if (BuiltinName.startswith("__builtin_") &&
@@ -1603,13 +1619,6 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
addDeferredDeclToEmit(F, DDI->second);
DeferredDecls.erase(DDI);
- // Otherwise, if this is a sized deallocation function, emit a weak
- // definition
- // for it at the end of the translation unit.
- } else if (D && cast<FunctionDecl>(D)
- ->getCorrespondingUnsizedGlobalDeallocationFunction()) {
- addDeferredDeclToEmit(F, GD);
-
// Otherwise, there are cases we have to worry about where we're
// using a declaration for which we must emit a definition but where
// we might not find a top-level definition:
@@ -1766,6 +1775,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
// handling.
GV->setConstant(isTypeConstant(D->getType(), false));
+ GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
+
setLinkageAndVisibilityForGV(GV, D);
if (D->getTLSKind()) {
@@ -1829,7 +1840,11 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
OldGV->eraseFromParent();
}
-
+
+ if (supportsCOMDAT() && GV->isWeakForLinker() &&
+ !GV->hasAvailableExternallyLinkage())
+ GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+
return GV;
}
@@ -1884,7 +1899,7 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D,
unsigned AddrSpace) {
- if (LangOpts.CUDA && CodeGenOpts.CUDAIsDevice) {
+ if (LangOpts.CUDA && LangOpts.CUDAIsDevice) {
if (D->hasAttr<CUDAConstantAttr>())
AddrSpace = getContext().getTargetAddressSpace(LangAS::cuda_constant);
else if (D->hasAttr<CUDASharedAttr>())
@@ -1929,6 +1944,38 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
R.first->second = nullptr;
}
+static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) {
+ if (!CGM.supportsCOMDAT())
+ return false;
+
+ if (D.hasAttr<SelectAnyAttr>())
+ return true;
+
+ GVALinkage Linkage;
+ if (auto *VD = dyn_cast<VarDecl>(&D))
+ Linkage = CGM.getContext().GetGVALinkageForVariable(VD);
+ else
+ Linkage = CGM.getContext().GetGVALinkageForFunction(cast<FunctionDecl>(&D));
+
+ switch (Linkage) {
+ case GVA_Internal:
+ case GVA_AvailableExternally:
+ case GVA_StrongExternal:
+ return false;
+ case GVA_DiscardableODR:
+ case GVA_StrongODR:
+ return true;
+ }
+ llvm_unreachable("No such linkage");
+}
+
+void CodeGenModule::maybeSetTrivialComdat(const Decl &D,
+ llvm::GlobalObject &GO) {
+ if (!shouldBeInCOMDAT(*this, D))
+ return;
+ GO.setComdat(TheModule.getOrInsertComdat(GO.getName()));
+}
+
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::Constant *Init = nullptr;
QualType ASTTy = D->getType();
@@ -2072,6 +2119,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
setTLSMode(GV, *D);
}
+ maybeSetTrivialComdat(*D, *GV);
+
// Emit the initializer function if necessary.
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
@@ -2085,7 +2134,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
}
static bool isVarDeclStrongDefinition(const ASTContext &Context,
- const VarDecl *D, bool NoCommon) {
+ CodeGenModule &CGM, const VarDecl *D,
+ bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
// was overridden by a NoCommon attribute.
if ((NoCommon || D->hasAttr<NoCommonAttr>()) && !D->hasAttr<CommonAttr>())
@@ -2110,11 +2160,31 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
if (D->hasAttr<WeakImportAttr>())
return true;
+ // A variable cannot be both common and exist in a comdat.
+ if (shouldBeInCOMDAT(CGM, *D))
+ return true;
+
// Declarations with a required alignment do not have common linakge in MSVC
// mode.
- if (Context.getLangOpts().MSVCCompat &&
- (Context.isAlignmentRequired(D->getType()) || D->hasAttr<AlignedAttr>()))
- return true;
+ if (Context.getLangOpts().MSVCCompat) {
+ if (D->hasAttr<AlignedAttr>())
+ return true;
+ QualType VarType = D->getType();
+ if (Context.isAlignmentRequired(VarType))
+ return true;
+
+ if (const auto *RT = VarType->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ for (const FieldDecl *FD : RD->fields()) {
+ if (FD->isBitField())
+ continue;
+ if (FD->hasAttr<AlignedAttr>())
+ return true;
+ if (Context.isAlignmentRequired(FD->getType()))
+ return true;
+ }
+ }
+ }
return false;
}
@@ -2162,7 +2232,7 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) &&
- !isVarDeclStrongDefinition(Context, cast<VarDecl>(D),
+ !isVarDeclStrongDefinition(Context, *this, cast<VarDecl>(D),
CodeGenOpts.NoCommon))
return llvm::GlobalVariable::CommonLinkage;
@@ -2285,7 +2355,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
callSite->replaceAllUsesWith(newCall.getInstruction());
// Copy debug location attached to CI.
- if (!callSite->getDebugLoc().isUnknown())
+ if (callSite->getDebugLoc())
newCall->setDebugLoc(callSite->getDebugLoc());
callSite->eraseFromParent();
}
@@ -2394,18 +2464,15 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
// declarations).
auto *Fn = cast<llvm::Function>(GV);
setFunctionLinkage(GD, Fn);
- if (D->hasAttr<DLLImportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (D->hasAttr<DLLExportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- else
- GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
+ setFunctionDLLStorageClass(GD, Fn);
// FIXME: this is redundant with part of setFunctionDefinitionAttributes
setGlobalVisibility(Fn, D);
MaybeHandleStaticInExternC(D, Fn);
+ maybeSetTrivialComdat(*D, *Fn);
+
CodeGenFunction(*this).GenerateCode(D, Fn, FI);
setFunctionDefinitionAttributes(D, Fn);
@@ -2449,7 +2516,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
// Create the new alias itself, but don't set a name yet.
auto *GA = llvm::GlobalAlias::create(
- cast<llvm::PointerType>(Aliasee->getType())->getElementType(), 0,
+ cast<llvm::PointerType>(Aliasee->getType()),
llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
if (Entry) {
@@ -2497,12 +2564,10 @@ llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
Tys);
}
-static llvm::StringMapEntry<llvm::Constant*> &
-GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
- const StringLiteral *Literal,
- bool TargetIsLSB,
- bool &IsUTF16,
- unsigned &StringLength) {
+static llvm::StringMapEntry<llvm::GlobalVariable *> &
+GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
+ const StringLiteral *Literal, bool TargetIsLSB,
+ bool &IsUTF16, unsigned &StringLength) {
StringRef String = Literal->getString();
unsigned NumBytes = String.size();
@@ -2534,10 +2599,9 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
nullptr)).first;
}
-static llvm::StringMapEntry<llvm::Constant*> &
-GetConstantStringEntry(llvm::StringMap<llvm::Constant*> &Map,
- const StringLiteral *Literal,
- unsigned &StringLength) {
+static llvm::StringMapEntry<llvm::GlobalVariable *> &
+GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
+ const StringLiteral *Literal, unsigned &StringLength) {
StringRef String = Literal->getString();
StringLength = String.size();
return *Map.insert(std::make_pair(String, nullptr)).first;
@@ -2547,10 +2611,10 @@ llvm::Constant *
CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
unsigned StringLength = 0;
bool isUTF16 = false;
- llvm::StringMapEntry<llvm::Constant*> &Entry =
- GetConstantCFStringEntry(CFConstantStringMap, Literal,
- getDataLayout().isLittleEndian(),
- isUTF16, StringLength);
+ llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
+ GetConstantCFStringEntry(CFConstantStringMap, Literal,
+ getDataLayout().isLittleEndian(), isUTF16,
+ StringLength);
if (auto *C = Entry.second)
return C;
@@ -2566,7 +2630,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *GV = CreateRuntimeVariable(Ty,
"__CFConstantStringClassReference");
// Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ V = llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
CFConstantStringClassRef = V;
}
else
@@ -2619,7 +2683,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
}
// String.
- Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ Fields[2] =
+ llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
if (isUTF16)
// Cast the UTF16 string to the correct type.
@@ -2640,11 +2705,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
return GV;
}
-llvm::Constant *
+llvm::GlobalVariable *
CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
unsigned StringLength = 0;
- llvm::StringMapEntry<llvm::Constant*> &Entry =
- GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
+ llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
+ GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
if (auto *C = Entry.second)
return C;
@@ -2673,11 +2738,10 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
llvm::Type *PTy = llvm::ArrayType::get(Ty, 0);
GV = CreateRuntimeVariable(PTy, str);
// Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ V = llvm::ConstantExpr::getGetElementPtr(PTy, GV, Zeros);
ConstantStringClassRef = V;
}
- }
- else
+ } else
V = ConstantStringClassRef;
if (!NSConstantStringType) {
@@ -2733,8 +2797,9 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
// of the string is via this class initializer.
CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
GV->setAlignment(Align.getQuantity());
- Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
-
+ Fields[1] =
+ llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
+
// String length.
llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
@@ -2838,12 +2903,18 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
if (CGM.getLangOpts().OpenCL)
AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
+ llvm::Module &M = CGM.getModule();
// Create a global variable for this string
auto *GV = new llvm::GlobalVariable(
- CGM.getModule(), C->getType(), !CGM.getLangOpts().WritableStrings, LT, C,
- GlobalName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace);
+ M, C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, GlobalName,
+ nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace);
GV->setAlignment(Alignment);
GV->setUnnamedAddr(true);
+ if (GV->isWeakForLinker()) {
+ assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals");
+ GV->setComdat(M.getOrInsertComdat(GV->getName()));
+ }
+
return GV;
}
@@ -3002,10 +3073,19 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
// Create a global variable for this lifetime-extended temporary.
llvm::GlobalValue::LinkageTypes Linkage =
getLLVMLinkageVarDefinition(VD, Constant);
- // There is no need for this temporary to have global linkage if the global
- // variable has external linkage.
- if (Linkage == llvm::GlobalVariable::ExternalLinkage)
- Linkage = llvm::GlobalVariable::PrivateLinkage;
+ if (Linkage == llvm::GlobalVariable::ExternalLinkage) {
+ const VarDecl *InitVD;
+ if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) &&
+ isa<CXXRecordDecl>(InitVD->getLexicalDeclContext())) {
+ // Temporaries defined inside a class get linkonce_odr linkage because the
+ // class can be defined in multipe translation units.
+ Linkage = llvm::GlobalVariable::LinkOnceODRLinkage;
+ } else {
+ // There is no need for this temporary to have external linkage if the
+ // VarDecl has external linkage.
+ Linkage = llvm::GlobalVariable::InternalLinkage;
+ }
+ }
unsigned AddrSpace = GetGlobalVarAddressSpace(
VD, getContext().getTargetAddressSpace(MaterializedType));
auto *GV = new llvm::GlobalVariable(
@@ -3015,6 +3095,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
setGlobalVisibility(GV, VD);
GV->setAlignment(
getContext().getTypeAlignInChars(MaterializedType).getQuantity());
+ if (supportsCOMDAT() && GV->isWeakForLinker())
+ GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
if (VD->getTLSKind())
setTLSMode(GV, *VD);
Slot = GV;
@@ -3268,16 +3350,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
break;
case Decl::FileScopeAsm: {
+ // File-scope asm is ignored during device-side CUDA compilation.
+ if (LangOpts.CUDA && LangOpts.CUDAIsDevice)
+ break;
auto *AD = cast<FileScopeAsmDecl>(D);
- StringRef AsmString = AD->getAsmString()->getString();
-
- const std::string &S = getModule().getModuleInlineAsm();
- if (S.empty())
- getModule().setModuleInlineAsm(AsmString);
- else if (S.end()[-1] == '\n')
- getModule().setModuleInlineAsm(S + AsmString.str());
- else
- getModule().setModuleInlineAsm(S + '\n' + AsmString.str());
+ getModule().appendModuleInlineAsm(AD->getAsmString()->getString());
break;
}
@@ -3285,11 +3362,13 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
auto *Import = cast<ImportDecl>(D);
// Ignore import declarations that come from imported modules.
- if (clang::Module *Owner = Import->getOwningModule()) {
+ if (clang::Module *Owner = Import->getImportedOwningModule()) {
if (getLangOpts().CurrentModule.empty() ||
Owner->getTopLevelModule()->Name == getLangOpts().CurrentModule)
break;
}
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitImportDecl(*Import);
ImportedModules.insert(Import->getImportedModule());
break;
@@ -3357,7 +3436,7 @@ void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
std::vector<const Decl *> DeferredDecls;
- for (const auto I : DeferredEmptyCoverageMappingDecls) {
+ for (const auto &I : DeferredEmptyCoverageMappingDecls) {
if (!I.second)
continue;
DeferredDecls.push_back(I.first);
@@ -3430,11 +3509,9 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
/// to such functions with an unmangled name from inline assembly within the
/// same translation unit.
void CodeGenModule::EmitStaticExternCAliases() {
- for (StaticExternCMap::iterator I = StaticExternCValues.begin(),
- E = StaticExternCValues.end();
- I != E; ++I) {
- IdentifierInfo *Name = I->first;
- llvm::GlobalValue *Val = I->second;
+ for (auto &I : StaticExternCValues) {
+ IdentifierInfo *Name = I.first;
+ llvm::GlobalValue *Val = I.second;
if (Val && !getModule().getNamedValue(Name->getName()))
addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val));
}
@@ -3561,6 +3638,12 @@ llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid) {
return llvm::ConstantStruct::getAnon(Fields);
}
+llvm::Constant *
+CodeGenModule::getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType) {
+ return getCXXABI().getAddrOfCXXCatchHandlerType(Ty, CatchHandlerType);
+}
+
llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
bool ForEH) {
// Return a bogus pointer if RTTI is disabled, unless it's for EH.
@@ -3583,11 +3666,22 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
VD->getAnyInitializer() &&
!VD->getAnyInitializer()->isConstantInitializer(getContext(),
/*ForRef=*/false);
- if (auto InitFunction =
- getOpenMPRuntime().EmitOMPThreadPrivateVarDefinition(
- VD, GetAddrOfGlobalVar(VD), RefExpr->getLocStart(),
- PerformInit))
+ if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition(
+ VD, GetAddrOfGlobalVar(VD), RefExpr->getLocStart(), PerformInit))
CXXGlobalInits.push_back(InitFunction);
}
}
+llvm::MDTuple *CodeGenModule::CreateVTableBitSetEntry(
+ llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD) {
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out);
+
+ llvm::Metadata *BitsetOps[] = {
+ llvm::MDString::get(getLLVMContext(), Out.str()),
+ llvm::ConstantAsMetadata::get(VTable),
+ llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
+ return llvm::MDTuple::get(getLLVMContext(), BitsetOps);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index 2aafe7e..dd167a2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -69,6 +69,8 @@ class ValueDecl;
class VarDecl;
class LangOptions;
class CodeGenOptions;
+class HeaderSearchOptions;
+class PreprocessorOptions;
class DiagnosticsEngine;
class AnnotateAttr;
class CXXDestructorDecl;
@@ -258,8 +260,8 @@ public:
/// This class organizes the cross-function state that is used while generating
/// LLVM code.
class CodeGenModule : public CodeGenTypeCache {
- CodeGenModule(const CodeGenModule &) LLVM_DELETED_FUNCTION;
- void operator=(const CodeGenModule &) LLVM_DELETED_FUNCTION;
+ CodeGenModule(const CodeGenModule &) = delete;
+ void operator=(const CodeGenModule &) = delete;
public:
struct Structor {
@@ -278,6 +280,8 @@ public:
private:
ASTContext &Context;
const LangOptions &LangOpts;
+ const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
+ const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions &CodeGenOpts;
llvm::Module &TheModule;
DiagnosticsEngine &Diags;
@@ -329,7 +333,7 @@ private:
};
std::vector<DeferredGlobal> DeferredDeclsToEmit;
void addDeferredDeclToEmit(llvm::GlobalValue *GV, GlobalDecl GD) {
- DeferredDeclsToEmit.push_back(DeferredGlobal(GV, GD));
+ DeferredDeclsToEmit.emplace_back(GV, GD);
}
/// List of alias we have emitted. Used to make sure that what they point to
@@ -366,7 +370,7 @@ private:
/// Map used to get unique annotation strings.
llvm::StringMap<llvm::Constant*> AnnotationStrings;
- llvm::StringMap<llvm::Constant*> CFConstantStringMap;
+ llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
@@ -400,7 +404,8 @@ private:
/// When a C++ decl with an initializer is deferred, null is
/// appended to CXXGlobalInits, and the index of that null is placed
/// here so that the initializer will be performed in the correct
- /// order.
+ /// order. Once the decl is emitted, the index is replaced with ~0U to ensure
+ /// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
@@ -487,7 +492,10 @@ private:
std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
public:
- CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
+ CodeGenModule(ASTContext &C,
+ const HeaderSearchOptions &headersearchopts,
+ const PreprocessorOptions &ppopts,
+ const CodeGenOptions &CodeGenOpts,
llvm::Module &M, const llvm::DataLayout &TD,
DiagnosticsEngine &Diags,
CoverageSourceInfo *CoverageInfo = nullptr);
@@ -599,6 +607,10 @@ public:
ASTContext &getContext() const { return Context; }
const LangOptions &getLangOpts() const { return LangOpts; }
+ const HeaderSearchOptions &getHeaderSearchOpts()
+ const { return HeaderSearchOpts; }
+ const PreprocessorOptions &getPreprocessorOpts()
+ const { return PreprocessorOpts; }
const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
llvm::Module &getModule() const { return TheModule; }
DiagnosticsEngine &getDiags() const { return Diags; }
@@ -606,6 +618,7 @@ public:
const TargetInfo &getTarget() const { return Target; }
const llvm::Triple &getTriple() const;
bool supportsCOMDAT() const;
+ void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO);
CGCXXABI &getCXXABI() const { return *ABI; }
llvm::LLVMContext &getLLVMContext() { return VMContext; }
@@ -718,6 +731,9 @@ public:
/// Get the address of the RTTI descriptor for the given type.
llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
+ llvm::Constant *getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType);
+
/// Get the address of a uuid descriptor .
llvm::Constant *GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
@@ -727,6 +743,11 @@ public:
/// Get a reference to the target of VD.
llvm::Constant *GetWeakRefReference(const ValueDecl *VD);
+ CharUnits
+ computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass,
+ CastExpr::path_const_iterator Start,
+ CastExpr::path_const_iterator End);
+
/// Returns the offset from a derived class to a class. Returns null if the
/// offset is 0.
llvm::Constant *
@@ -782,7 +803,7 @@ public:
/// Return a pointer to a constant NSString object for the given string. Or a
/// user defined String object as defined via
/// -fconstant-string-class=class_name option.
- llvm::Constant *GetAddrOfConstantString(const StringLiteral *Literal);
+ llvm::GlobalVariable *GetAddrOfConstantString(const StringLiteral *Literal);
/// Return a constant array for the given string.
llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E);
@@ -871,7 +892,7 @@ public:
/// Add a destructor and object to add to the C++ global destructor function.
void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
- CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
+ CXXGlobalDtors.emplace_back(DtorFn, Object);
}
/// Create a new runtime function with the specified type and name.
@@ -993,7 +1014,7 @@ public:
void EmitTentativeDefinition(const VarDecl *D);
- void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
+ void EmitVTable(CXXRecordDecl *Class);
/// Emit the RTTI descriptors for the builtin types.
void EmitFundamentalRTTIDescriptors();
@@ -1013,6 +1034,9 @@ public:
F->setLinkage(getFunctionLinkage(GD));
}
+ /// Set the DLL storage class on F.
+ void setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F);
+
/// Return the appropriate linkage for the vtable, VTT, and type information
/// of the given class.
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
@@ -1102,6 +1126,23 @@ 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,
+ const VTableLayout &VTLayout);
+
+ /// Create a bitset entry for the given vtable.
+ llvm::MDTuple *CreateVTableBitSetEntry(llvm::GlobalVariable *VTable,
+ CharUnits Offset,
+ const CXXRecordDecl *RD);
+
+ /// \breif Get the declaration of std::terminate for the platform.
+ llvm::Constant *getTerminateFn();
+
private:
llvm::Constant *
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
index 24b035d..8dffefc 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -58,12 +58,16 @@ void CodeGenPGO::setFuncName(llvm::Function *Fn) {
}
void CodeGenPGO::createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage) {
- // Usually, we want to match the function's linkage, but
- // available_externally and extern_weak both have the wrong semantics.
+ // We generally want to match the function's linkage, but available_externally
+ // and extern_weak both have the wrong semantics, and anything that doesn't
+ // need to link across compilation units doesn't need to be visible at all.
if (Linkage == llvm::GlobalValue::ExternalWeakLinkage)
Linkage = llvm::GlobalValue::LinkOnceAnyLinkage;
else if (Linkage == llvm::GlobalValue::AvailableExternallyLinkage)
Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
+ else if (Linkage == llvm::GlobalValue::InternalLinkage ||
+ Linkage == llvm::GlobalValue::ExternalLinkage)
+ Linkage = llvm::GlobalValue::PrivateLinkage;
auto *Value =
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), FuncName, false);
@@ -138,482 +142,468 @@ const int PGOHash::NumBitsPerType;
const unsigned PGOHash::NumTypesPerWord;
const unsigned PGOHash::TooBig;
- /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
- struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
- /// The next counter value to assign.
- unsigned NextCounter;
- /// The function hash.
- PGOHash Hash;
- /// The map of statements to counters.
- llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
-
- MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
- : NextCounter(0), CounterMap(CounterMap) {}
-
- // Blocks and lambdas are handled as separate functions, so we need not
- // traverse them in the parent context.
- bool TraverseBlockExpr(BlockExpr *BE) { return true; }
- bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
- bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
-
- bool VisitDecl(const Decl *D) {
- switch (D->getKind()) {
- default:
- break;
- case Decl::Function:
- case Decl::CXXMethod:
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- case Decl::ObjCMethod:
- case Decl::Block:
- case Decl::Captured:
- CounterMap[D->getBody()] = NextCounter++;
- break;
- }
- return true;
+/// A RecursiveASTVisitor that fills a map of statements to PGO counters.
+struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
+ /// The next counter value to assign.
+ unsigned NextCounter;
+ /// The function hash.
+ PGOHash Hash;
+ /// The map of statements to counters.
+ llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
+
+ MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
+ : NextCounter(0), CounterMap(CounterMap) {}
+
+ // Blocks and lambdas are handled as separate functions, so we need not
+ // traverse them in the parent context.
+ bool TraverseBlockExpr(BlockExpr *BE) { return true; }
+ bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
+ bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
+
+ bool VisitDecl(const Decl *D) {
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::ObjCMethod:
+ case Decl::Block:
+ case Decl::Captured:
+ CounterMap[D->getBody()] = NextCounter++;
+ break;
}
+ return true;
+ }
- bool VisitStmt(const Stmt *S) {
- auto Type = getHashType(S);
- if (Type == PGOHash::None)
- return true;
-
- CounterMap[S] = NextCounter++;
- Hash.combine(Type);
+ bool VisitStmt(const Stmt *S) {
+ auto Type = getHashType(S);
+ if (Type == PGOHash::None)
return true;
+
+ CounterMap[S] = NextCounter++;
+ Hash.combine(Type);
+ return true;
+ }
+ PGOHash::HashType getHashType(const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default:
+ break;
+ case Stmt::LabelStmtClass:
+ return PGOHash::LabelStmt;
+ case Stmt::WhileStmtClass:
+ return PGOHash::WhileStmt;
+ case Stmt::DoStmtClass:
+ return PGOHash::DoStmt;
+ case Stmt::ForStmtClass:
+ return PGOHash::ForStmt;
+ case Stmt::CXXForRangeStmtClass:
+ return PGOHash::CXXForRangeStmt;
+ case Stmt::ObjCForCollectionStmtClass:
+ return PGOHash::ObjCForCollectionStmt;
+ case Stmt::SwitchStmtClass:
+ return PGOHash::SwitchStmt;
+ case Stmt::CaseStmtClass:
+ return PGOHash::CaseStmt;
+ case Stmt::DefaultStmtClass:
+ return PGOHash::DefaultStmt;
+ case Stmt::IfStmtClass:
+ return PGOHash::IfStmt;
+ case Stmt::CXXTryStmtClass:
+ return PGOHash::CXXTryStmt;
+ case Stmt::CXXCatchStmtClass:
+ return PGOHash::CXXCatchStmt;
+ case Stmt::ConditionalOperatorClass:
+ return PGOHash::ConditionalOperator;
+ case Stmt::BinaryConditionalOperatorClass:
+ return PGOHash::BinaryConditionalOperator;
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(S);
+ if (BO->getOpcode() == BO_LAnd)
+ return PGOHash::BinaryOperatorLAnd;
+ if (BO->getOpcode() == BO_LOr)
+ return PGOHash::BinaryOperatorLOr;
+ break;
}
- PGOHash::HashType getHashType(const Stmt *S) {
- switch (S->getStmtClass()) {
- default:
- break;
- case Stmt::LabelStmtClass:
- return PGOHash::LabelStmt;
- case Stmt::WhileStmtClass:
- return PGOHash::WhileStmt;
- case Stmt::DoStmtClass:
- return PGOHash::DoStmt;
- case Stmt::ForStmtClass:
- return PGOHash::ForStmt;
- case Stmt::CXXForRangeStmtClass:
- return PGOHash::CXXForRangeStmt;
- case Stmt::ObjCForCollectionStmtClass:
- return PGOHash::ObjCForCollectionStmt;
- case Stmt::SwitchStmtClass:
- return PGOHash::SwitchStmt;
- case Stmt::CaseStmtClass:
- return PGOHash::CaseStmt;
- case Stmt::DefaultStmtClass:
- return PGOHash::DefaultStmt;
- case Stmt::IfStmtClass:
- return PGOHash::IfStmt;
- case Stmt::CXXTryStmtClass:
- return PGOHash::CXXTryStmt;
- case Stmt::CXXCatchStmtClass:
- return PGOHash::CXXCatchStmt;
- case Stmt::ConditionalOperatorClass:
- return PGOHash::ConditionalOperator;
- case Stmt::BinaryConditionalOperatorClass:
- return PGOHash::BinaryConditionalOperator;
- case Stmt::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(S);
- if (BO->getOpcode() == BO_LAnd)
- return PGOHash::BinaryOperatorLAnd;
- if (BO->getOpcode() == BO_LOr)
- return PGOHash::BinaryOperatorLOr;
- break;
- }
- }
- return PGOHash::None;
}
+ return PGOHash::None;
+ }
+};
+
+/// A StmtVisitor that propagates the raw counts through the AST and
+/// records the count at statements where the value may change.
+struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
+ /// PGO state.
+ CodeGenPGO &PGO;
+
+ /// A flag that is set when the current count should be recorded on the
+ /// next statement, such as at the exit of a loop.
+ bool RecordNextStmtCount;
+
+ /// The count at the current location in the traversal.
+ uint64_t CurrentCount;
+
+ /// The map of statements to count values.
+ llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
+
+ /// BreakContinueStack - Keep counts of breaks and continues inside loops.
+ struct BreakContinue {
+ uint64_t BreakCount;
+ uint64_t ContinueCount;
+ BreakContinue() : BreakCount(0), ContinueCount(0) {}
};
+ SmallVector<BreakContinue, 8> BreakContinueStack;
- /// A StmtVisitor that propagates the raw counts through the AST and
- /// records the count at statements where the value may change.
- struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
- /// PGO state.
- CodeGenPGO &PGO;
-
- /// A flag that is set when the current count should be recorded on the
- /// next statement, such as at the exit of a loop.
- bool RecordNextStmtCount;
-
- /// The map of statements to count values.
- llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
-
- /// BreakContinueStack - Keep counts of breaks and continues inside loops.
- struct BreakContinue {
- uint64_t BreakCount;
- uint64_t ContinueCount;
- BreakContinue() : BreakCount(0), ContinueCount(0) {}
- };
- SmallVector<BreakContinue, 8> BreakContinueStack;
-
- ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
- CodeGenPGO &PGO)
- : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
-
- void RecordStmtCount(const Stmt *S) {
- if (RecordNextStmtCount) {
- CountMap[S] = PGO.getCurrentRegionCount();
- RecordNextStmtCount = false;
- }
- }
+ ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
+ CodeGenPGO &PGO)
+ : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
- void VisitStmt(const Stmt *S) {
- RecordStmtCount(S);
- for (Stmt::const_child_range I = S->children(); I; ++I) {
- if (*I)
- this->Visit(*I);
- }
+ void RecordStmtCount(const Stmt *S) {
+ if (RecordNextStmtCount) {
+ CountMap[S] = CurrentCount;
+ RecordNextStmtCount = false;
}
+ }
- void VisitFunctionDecl(const FunctionDecl *D) {
- // Counter tracks entry to the function body.
- RegionCounter Cnt(PGO, D->getBody());
- Cnt.beginRegion();
- CountMap[D->getBody()] = PGO.getCurrentRegionCount();
- Visit(D->getBody());
- }
+ /// Set and return the current count.
+ uint64_t setCount(uint64_t Count) {
+ CurrentCount = Count;
+ return Count;
+ }
- // Skip lambda expressions. We visit these as FunctionDecls when we're
- // generating them and aren't interested in the body when generating a
- // parent context.
- void VisitLambdaExpr(const LambdaExpr *LE) {}
-
- void VisitCapturedDecl(const CapturedDecl *D) {
- // Counter tracks entry to the capture body.
- RegionCounter Cnt(PGO, D->getBody());
- Cnt.beginRegion();
- CountMap[D->getBody()] = PGO.getCurrentRegionCount();
- Visit(D->getBody());
- }
+ void VisitStmt(const Stmt *S) {
+ RecordStmtCount(S);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ this->Visit(Child);
+ }
- void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
- // Counter tracks entry to the method body.
- RegionCounter Cnt(PGO, D->getBody());
- Cnt.beginRegion();
- CountMap[D->getBody()] = PGO.getCurrentRegionCount();
- Visit(D->getBody());
- }
+ void VisitFunctionDecl(const FunctionDecl *D) {
+ // Counter tracks entry to the function body.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
+ CountMap[D->getBody()] = BodyCount;
+ Visit(D->getBody());
+ }
- void VisitBlockDecl(const BlockDecl *D) {
- // Counter tracks entry to the block body.
- RegionCounter Cnt(PGO, D->getBody());
- Cnt.beginRegion();
- CountMap[D->getBody()] = PGO.getCurrentRegionCount();
- Visit(D->getBody());
- }
+ // Skip lambda expressions. We visit these as FunctionDecls when we're
+ // generating them and aren't interested in the body when generating a
+ // parent context.
+ void VisitLambdaExpr(const LambdaExpr *LE) {}
- void VisitReturnStmt(const ReturnStmt *S) {
- RecordStmtCount(S);
- if (S->getRetValue())
- Visit(S->getRetValue());
- PGO.setCurrentRegionUnreachable();
- RecordNextStmtCount = true;
- }
+ void VisitCapturedDecl(const CapturedDecl *D) {
+ // Counter tracks entry to the capture body.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
+ CountMap[D->getBody()] = BodyCount;
+ Visit(D->getBody());
+ }
- void VisitGotoStmt(const GotoStmt *S) {
- RecordStmtCount(S);
- PGO.setCurrentRegionUnreachable();
- RecordNextStmtCount = true;
- }
+ void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+ // Counter tracks entry to the method body.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
+ CountMap[D->getBody()] = BodyCount;
+ Visit(D->getBody());
+ }
- void VisitLabelStmt(const LabelStmt *S) {
- RecordNextStmtCount = false;
- // Counter tracks the block following the label.
- RegionCounter Cnt(PGO, S);
- Cnt.beginRegion();
- CountMap[S] = PGO.getCurrentRegionCount();
- Visit(S->getSubStmt());
- }
+ void VisitBlockDecl(const BlockDecl *D) {
+ // Counter tracks entry to the block body.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
+ CountMap[D->getBody()] = BodyCount;
+ Visit(D->getBody());
+ }
- void VisitBreakStmt(const BreakStmt *S) {
- RecordStmtCount(S);
- assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
- BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount();
- PGO.setCurrentRegionUnreachable();
- RecordNextStmtCount = true;
- }
+ void VisitReturnStmt(const ReturnStmt *S) {
+ RecordStmtCount(S);
+ if (S->getRetValue())
+ Visit(S->getRetValue());
+ CurrentCount = 0;
+ RecordNextStmtCount = true;
+ }
- void VisitContinueStmt(const ContinueStmt *S) {
- RecordStmtCount(S);
- assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
- BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount();
- PGO.setCurrentRegionUnreachable();
- RecordNextStmtCount = true;
- }
+ void VisitCXXThrowExpr(const CXXThrowExpr *E) {
+ RecordStmtCount(E);
+ if (E->getSubExpr())
+ Visit(E->getSubExpr());
+ CurrentCount = 0;
+ RecordNextStmtCount = true;
+ }
- void VisitWhileStmt(const WhileStmt *S) {
- RecordStmtCount(S);
- // Counter tracks the body of the loop.
- RegionCounter Cnt(PGO, S);
- BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first so the break/continue adjustments can be
- // included when visiting the condition.
- Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
-
- // ...then go back and propagate counts through the condition. The count
- // at the start of the condition is the sum of the incoming edges,
- // the backedge from the end of the loop body, and the edges from
- // continue statements.
- BreakContinue BC = BreakContinueStack.pop_back_val();
- Cnt.setCurrentRegionCount(Cnt.getParentCount() +
- Cnt.getAdjustedCount() + BC.ContinueCount);
- CountMap[S->getCond()] = PGO.getCurrentRegionCount();
- Visit(S->getCond());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
- RecordNextStmtCount = true;
- }
+ void VisitGotoStmt(const GotoStmt *S) {
+ RecordStmtCount(S);
+ CurrentCount = 0;
+ RecordNextStmtCount = true;
+ }
- void VisitDoStmt(const DoStmt *S) {
- RecordStmtCount(S);
- // Counter tracks the body of the loop.
- RegionCounter Cnt(PGO, S);
- BreakContinueStack.push_back(BreakContinue());
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
-
- BreakContinue BC = BreakContinueStack.pop_back_val();
- // The count at the start of the condition is equal to the count at the
- // end of the body. The adjusted count does not include either the
- // fall-through count coming into the loop or the continue count, so add
- // both of those separately. This is coincidentally the same equation as
- // with while loops but for different reasons.
- Cnt.setCurrentRegionCount(Cnt.getParentCount() +
- Cnt.getAdjustedCount() + BC.ContinueCount);
- CountMap[S->getCond()] = PGO.getCurrentRegionCount();
- Visit(S->getCond());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
- RecordNextStmtCount = true;
- }
+ void VisitLabelStmt(const LabelStmt *S) {
+ RecordNextStmtCount = false;
+ // Counter tracks the block following the label.
+ uint64_t BlockCount = setCount(PGO.getRegionCount(S));
+ CountMap[S] = BlockCount;
+ Visit(S->getSubStmt());
+ }
- void VisitForStmt(const ForStmt *S) {
- RecordStmtCount(S);
- if (S->getInit())
- Visit(S->getInit());
- // Counter tracks the body of the loop.
- RegionCounter Cnt(PGO, S);
- BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first. (This is basically the same as a while
- // loop; see further comments in VisitWhileStmt.)
- Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
-
- // The increment is essentially part of the body but it needs to include
- // the count for all the continue statements.
- if (S->getInc()) {
- Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
- BreakContinueStack.back().ContinueCount);
- CountMap[S->getInc()] = PGO.getCurrentRegionCount();
- Visit(S->getInc());
- Cnt.adjustForControlFlow();
- }
-
- BreakContinue BC = BreakContinueStack.pop_back_val();
-
- // ...then go back and propagate counts through the condition.
- if (S->getCond()) {
- Cnt.setCurrentRegionCount(Cnt.getParentCount() +
- Cnt.getAdjustedCount() +
- BC.ContinueCount);
- CountMap[S->getCond()] = PGO.getCurrentRegionCount();
- Visit(S->getCond());
- Cnt.adjustForControlFlow();
- }
- Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
- RecordNextStmtCount = true;
- }
+ void VisitBreakStmt(const BreakStmt *S) {
+ RecordStmtCount(S);
+ assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
+ BreakContinueStack.back().BreakCount += CurrentCount;
+ CurrentCount = 0;
+ RecordNextStmtCount = true;
+ }
- void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
- RecordStmtCount(S);
- Visit(S->getRangeStmt());
- Visit(S->getBeginEndStmt());
- // Counter tracks the body of the loop.
- RegionCounter Cnt(PGO, S);
- BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first. (This is basically the same as a while
- // loop; see further comments in VisitWhileStmt.)
- Cnt.beginRegion();
- CountMap[S->getLoopVarStmt()] = PGO.getCurrentRegionCount();
- Visit(S->getLoopVarStmt());
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
-
- // The increment is essentially part of the body but it needs to include
- // the count for all the continue statements.
- Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
- BreakContinueStack.back().ContinueCount);
- CountMap[S->getInc()] = PGO.getCurrentRegionCount();
- Visit(S->getInc());
- Cnt.adjustForControlFlow();
+ void VisitContinueStmt(const ContinueStmt *S) {
+ RecordStmtCount(S);
+ assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
+ BreakContinueStack.back().ContinueCount += CurrentCount;
+ CurrentCount = 0;
+ RecordNextStmtCount = true;
+ }
- BreakContinue BC = BreakContinueStack.pop_back_val();
+ void VisitWhileStmt(const WhileStmt *S) {
+ RecordStmtCount(S);
+ uint64_t ParentCount = CurrentCount;
+
+ BreakContinueStack.push_back(BreakContinue());
+ // Visit the body region first so the break/continue adjustments can be
+ // included when visiting the condition.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(S));
+ CountMap[S->getBody()] = CurrentCount;
+ Visit(S->getBody());
+ uint64_t BackedgeCount = CurrentCount;
+
+ // ...then go back and propagate counts through the condition. The count
+ // at the start of the condition is the sum of the incoming edges,
+ // the backedge from the end of the loop body, and the edges from
+ // continue statements.
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+ uint64_t CondCount =
+ setCount(ParentCount + BackedgeCount + BC.ContinueCount);
+ CountMap[S->getCond()] = CondCount;
+ Visit(S->getCond());
+ setCount(BC.BreakCount + CondCount - BodyCount);
+ RecordNextStmtCount = true;
+ }
- // ...then go back and propagate counts through the condition.
- Cnt.setCurrentRegionCount(Cnt.getParentCount() +
- Cnt.getAdjustedCount() +
- BC.ContinueCount);
- CountMap[S->getCond()] = PGO.getCurrentRegionCount();
- Visit(S->getCond());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
- RecordNextStmtCount = true;
- }
+ void VisitDoStmt(const DoStmt *S) {
+ RecordStmtCount(S);
+ uint64_t LoopCount = PGO.getRegionCount(S);
+
+ BreakContinueStack.push_back(BreakContinue());
+ // The count doesn't include the fallthrough from the parent scope. Add it.
+ uint64_t BodyCount = setCount(LoopCount + CurrentCount);
+ CountMap[S->getBody()] = BodyCount;
+ Visit(S->getBody());
+ uint64_t BackedgeCount = CurrentCount;
+
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+ // The count at the start of the condition is equal to the count at the
+ // end of the body, plus any continues.
+ uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
+ CountMap[S->getCond()] = CondCount;
+ Visit(S->getCond());
+ setCount(BC.BreakCount + CondCount - LoopCount);
+ RecordNextStmtCount = true;
+ }
- void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
- RecordStmtCount(S);
- Visit(S->getElement());
- // Counter tracks the body of the loop.
- RegionCounter Cnt(PGO, S);
- BreakContinueStack.push_back(BreakContinue());
- Cnt.beginRegion();
- CountMap[S->getBody()] = PGO.getCurrentRegionCount();
- Visit(S->getBody());
- BreakContinue BC = BreakContinueStack.pop_back_val();
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
- RecordNextStmtCount = true;
+ void VisitForStmt(const ForStmt *S) {
+ RecordStmtCount(S);
+ if (S->getInit())
+ Visit(S->getInit());
+
+ uint64_t ParentCount = CurrentCount;
+
+ BreakContinueStack.push_back(BreakContinue());
+ // Visit the body region first. (This is basically the same as a while
+ // loop; see further comments in VisitWhileStmt.)
+ uint64_t BodyCount = setCount(PGO.getRegionCount(S));
+ CountMap[S->getBody()] = BodyCount;
+ Visit(S->getBody());
+ uint64_t BackedgeCount = CurrentCount;
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+
+ // The increment is essentially part of the body but it needs to include
+ // the count for all the continue statements.
+ if (S->getInc()) {
+ uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
+ CountMap[S->getInc()] = IncCount;
+ Visit(S->getInc());
}
- void VisitSwitchStmt(const SwitchStmt *S) {
- RecordStmtCount(S);
+ // ...then go back and propagate counts through the condition.
+ uint64_t CondCount =
+ setCount(ParentCount + BackedgeCount + BC.ContinueCount);
+ if (S->getCond()) {
+ CountMap[S->getCond()] = CondCount;
Visit(S->getCond());
- PGO.setCurrentRegionUnreachable();
- BreakContinueStack.push_back(BreakContinue());
- Visit(S->getBody());
- // If the switch is inside a loop, add the continue counts.
- BreakContinue BC = BreakContinueStack.pop_back_val();
- if (!BreakContinueStack.empty())
- BreakContinueStack.back().ContinueCount += BC.ContinueCount;
- // Counter tracks the exit block of the switch.
- RegionCounter ExitCnt(PGO, S);
- ExitCnt.beginRegion();
- RecordNextStmtCount = true;
}
+ setCount(BC.BreakCount + CondCount - BodyCount);
+ RecordNextStmtCount = true;
+ }
- void VisitCaseStmt(const CaseStmt *S) {
- RecordNextStmtCount = false;
- // Counter for this particular case. This counts only jumps from the
- // switch header and does not include fallthrough from the case before
- // this one.
- RegionCounter Cnt(PGO, S);
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- CountMap[S] = Cnt.getCount();
- RecordNextStmtCount = true;
- Visit(S->getSubStmt());
- }
+ void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
+ RecordStmtCount(S);
+ Visit(S->getLoopVarStmt());
+ Visit(S->getRangeStmt());
+ Visit(S->getBeginEndStmt());
+
+ uint64_t ParentCount = CurrentCount;
+ BreakContinueStack.push_back(BreakContinue());
+ // Visit the body region first. (This is basically the same as a while
+ // loop; see further comments in VisitWhileStmt.)
+ uint64_t BodyCount = setCount(PGO.getRegionCount(S));
+ CountMap[S->getBody()] = BodyCount;
+ Visit(S->getBody());
+ uint64_t BackedgeCount = CurrentCount;
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+
+ // The increment is essentially part of the body but it needs to include
+ // the count for all the continue statements.
+ uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
+ CountMap[S->getInc()] = IncCount;
+ Visit(S->getInc());
+
+ // ...then go back and propagate counts through the condition.
+ uint64_t CondCount =
+ setCount(ParentCount + BackedgeCount + BC.ContinueCount);
+ CountMap[S->getCond()] = CondCount;
+ Visit(S->getCond());
+ setCount(BC.BreakCount + CondCount - BodyCount);
+ RecordNextStmtCount = true;
+ }
- void VisitDefaultStmt(const DefaultStmt *S) {
- RecordNextStmtCount = false;
- // Counter for this default case. This does not include fallthrough from
- // the previous case.
- RegionCounter Cnt(PGO, S);
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- CountMap[S] = Cnt.getCount();
- RecordNextStmtCount = true;
- Visit(S->getSubStmt());
- }
+ void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
+ RecordStmtCount(S);
+ Visit(S->getElement());
+ uint64_t ParentCount = CurrentCount;
+ BreakContinueStack.push_back(BreakContinue());
+ // Counter tracks the body of the loop.
+ uint64_t BodyCount = setCount(PGO.getRegionCount(S));
+ CountMap[S->getBody()] = BodyCount;
+ Visit(S->getBody());
+ uint64_t BackedgeCount = CurrentCount;
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+
+ setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
+ BodyCount);
+ RecordNextStmtCount = true;
+ }
- void VisitIfStmt(const IfStmt *S) {
- RecordStmtCount(S);
- // Counter tracks the "then" part of an if statement. The count for
- // the "else" part, if it exists, will be calculated from this counter.
- RegionCounter Cnt(PGO, S);
- Visit(S->getCond());
+ void VisitSwitchStmt(const SwitchStmt *S) {
+ RecordStmtCount(S);
+ Visit(S->getCond());
+ CurrentCount = 0;
+ BreakContinueStack.push_back(BreakContinue());
+ Visit(S->getBody());
+ // If the switch is inside a loop, add the continue counts.
+ BreakContinue BC = BreakContinueStack.pop_back_val();
+ if (!BreakContinueStack.empty())
+ BreakContinueStack.back().ContinueCount += BC.ContinueCount;
+ // Counter tracks the exit block of the switch.
+ setCount(PGO.getRegionCount(S));
+ RecordNextStmtCount = true;
+ }
- Cnt.beginRegion();
- CountMap[S->getThen()] = PGO.getCurrentRegionCount();
- Visit(S->getThen());
- Cnt.adjustForControlFlow();
-
- if (S->getElse()) {
- Cnt.beginElseRegion();
- CountMap[S->getElse()] = PGO.getCurrentRegionCount();
- Visit(S->getElse());
- Cnt.adjustForControlFlow();
- }
- Cnt.applyAdjustmentsToRegion(0);
- RecordNextStmtCount = true;
- }
+ void VisitSwitchCase(const SwitchCase *S) {
+ RecordNextStmtCount = false;
+ // Counter for this particular case. This counts only jumps from the
+ // switch header and does not include fallthrough from the case before
+ // this one.
+ uint64_t CaseCount = PGO.getRegionCount(S);
+ setCount(CurrentCount + CaseCount);
+ // We need the count without fallthrough in the mapping, so it's more useful
+ // for branch probabilities.
+ CountMap[S] = CaseCount;
+ RecordNextStmtCount = true;
+ Visit(S->getSubStmt());
+ }
- void VisitCXXTryStmt(const CXXTryStmt *S) {
- RecordStmtCount(S);
- Visit(S->getTryBlock());
- for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
- Visit(S->getHandler(I));
- // Counter tracks the continuation block of the try statement.
- RegionCounter Cnt(PGO, S);
- Cnt.beginRegion();
- RecordNextStmtCount = true;
- }
+ void VisitIfStmt(const IfStmt *S) {
+ RecordStmtCount(S);
+ uint64_t ParentCount = CurrentCount;
+ Visit(S->getCond());
+
+ // Counter tracks the "then" part of an if statement. The count for
+ // the "else" part, if it exists, will be calculated from this counter.
+ uint64_t ThenCount = setCount(PGO.getRegionCount(S));
+ CountMap[S->getThen()] = ThenCount;
+ Visit(S->getThen());
+ uint64_t OutCount = CurrentCount;
+
+ uint64_t ElseCount = ParentCount - ThenCount;
+ if (S->getElse()) {
+ setCount(ElseCount);
+ CountMap[S->getElse()] = ElseCount;
+ Visit(S->getElse());
+ OutCount += CurrentCount;
+ } else
+ OutCount += ElseCount;
+ setCount(OutCount);
+ RecordNextStmtCount = true;
+ }
- void VisitCXXCatchStmt(const CXXCatchStmt *S) {
- RecordNextStmtCount = false;
- // Counter tracks the catch statement's handler block.
- RegionCounter Cnt(PGO, S);
- Cnt.beginRegion();
- CountMap[S] = PGO.getCurrentRegionCount();
- Visit(S->getHandlerBlock());
- }
+ void VisitCXXTryStmt(const CXXTryStmt *S) {
+ RecordStmtCount(S);
+ Visit(S->getTryBlock());
+ for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
+ Visit(S->getHandler(I));
+ // Counter tracks the continuation block of the try statement.
+ setCount(PGO.getRegionCount(S));
+ RecordNextStmtCount = true;
+ }
- void VisitAbstractConditionalOperator(
- const AbstractConditionalOperator *E) {
- RecordStmtCount(E);
- // Counter tracks the "true" part of a conditional operator. The
- // count in the "false" part will be calculated from this counter.
- RegionCounter Cnt(PGO, E);
- Visit(E->getCond());
-
- Cnt.beginRegion();
- CountMap[E->getTrueExpr()] = PGO.getCurrentRegionCount();
- Visit(E->getTrueExpr());
- Cnt.adjustForControlFlow();
-
- Cnt.beginElseRegion();
- CountMap[E->getFalseExpr()] = PGO.getCurrentRegionCount();
- Visit(E->getFalseExpr());
- Cnt.adjustForControlFlow();
-
- Cnt.applyAdjustmentsToRegion(0);
- RecordNextStmtCount = true;
- }
+ void VisitCXXCatchStmt(const CXXCatchStmt *S) {
+ RecordNextStmtCount = false;
+ // Counter tracks the catch statement's handler block.
+ uint64_t CatchCount = setCount(PGO.getRegionCount(S));
+ CountMap[S] = CatchCount;
+ Visit(S->getHandlerBlock());
+ }
- void VisitBinLAnd(const BinaryOperator *E) {
- RecordStmtCount(E);
- // Counter tracks the right hand side of a logical and operator.
- RegionCounter Cnt(PGO, E);
- Visit(E->getLHS());
- Cnt.beginRegion();
- CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
- Visit(E->getRHS());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(0);
- RecordNextStmtCount = true;
- }
+ void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ RecordStmtCount(E);
+ uint64_t ParentCount = CurrentCount;
+ Visit(E->getCond());
+
+ // Counter tracks the "true" part of a conditional operator. The
+ // count in the "false" part will be calculated from this counter.
+ uint64_t TrueCount = setCount(PGO.getRegionCount(E));
+ CountMap[E->getTrueExpr()] = TrueCount;
+ Visit(E->getTrueExpr());
+ uint64_t OutCount = CurrentCount;
+
+ uint64_t FalseCount = setCount(ParentCount - TrueCount);
+ CountMap[E->getFalseExpr()] = FalseCount;
+ Visit(E->getFalseExpr());
+ OutCount += CurrentCount;
+
+ setCount(OutCount);
+ RecordNextStmtCount = true;
+ }
- void VisitBinLOr(const BinaryOperator *E) {
- RecordStmtCount(E);
- // Counter tracks the right hand side of a logical or operator.
- RegionCounter Cnt(PGO, E);
- Visit(E->getLHS());
- Cnt.beginRegion();
- CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
- Visit(E->getRHS());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(0);
- RecordNextStmtCount = true;
- }
- };
+ void VisitBinLAnd(const BinaryOperator *E) {
+ RecordStmtCount(E);
+ uint64_t ParentCount = CurrentCount;
+ Visit(E->getLHS());
+ // Counter tracks the right hand side of a logical and operator.
+ uint64_t RHSCount = setCount(PGO.getRegionCount(E));
+ CountMap[E->getRHS()] = RHSCount;
+ Visit(E->getRHS());
+ setCount(ParentCount + RHSCount - CurrentCount);
+ RecordNextStmtCount = true;
+ }
+
+ void VisitBinLOr(const BinaryOperator *E) {
+ RecordStmtCount(E);
+ uint64_t ParentCount = CurrentCount;
+ Visit(E->getLHS());
+ // Counter tracks the right hand side of a logical or operator.
+ uint64_t RHSCount = setCount(PGO.getRegionCount(E));
+ CountMap[E->getRHS()] = RHSCount;
+ Visit(E->getRHS());
+ setCount(ParentCount + RHSCount - CurrentCount);
+ RecordNextStmtCount = true;
+ }
+};
}
void PGOHash::combine(HashType Type) {
@@ -728,12 +718,10 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
}
void
-CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
+CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
llvm::GlobalValue::LinkageTypes Linkage) {
if (SkipCoverageMapping)
return;
- setFuncName(FuncName, Linkage);
-
// Don't map the functions inside the system headers
auto Loc = D->getBody()->getLocStart();
if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
@@ -750,6 +738,7 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
if (CoverageMapping.empty())
return;
+ setFuncName(Name, Linkage);
CGM.getCoverageMapping()->addFunctionMappingRecord(
FuncNameVar, FuncName, FunctionHash, CoverageMapping);
}
@@ -783,19 +772,23 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
// Turn on Cold attribute for cold functions.
// FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal.
Fn->addFnAttr(llvm::Attribute::Cold);
+
+ Fn->setEntryCount(FunctionCount);
}
-void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
+void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S) {
if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
return;
if (!Builder.GetInsertPoint())
return;
+
+ unsigned Counter = (*RegionCounterMap)[S];
auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
- Builder.CreateCall4(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
- llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
+ {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(NumRegionCounters),
- Builder.getInt32(Counter));
+ Builder.getInt32(Counter)});
}
void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
@@ -839,8 +832,8 @@ static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
return Scaled;
}
-llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount,
- uint64_t FalseCount) {
+llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
+ uint64_t FalseCount) {
// Check for empty weights.
if (!TrueCount && !FalseCount)
return nullptr;
@@ -853,7 +846,8 @@ llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount,
scaleBranchWeight(FalseCount, Scale));
}
-llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) {
+llvm::MDNode *
+CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) {
// We need at least two elements to create meaningful weights.
if (Weights.size() < 2)
return nullptr;
@@ -875,17 +869,14 @@ llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) {
return MDHelper.createBranchWeights(ScaledWeights);
}
-llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond,
- RegionCounter &Cnt) {
- if (!haveRegionCounts())
+llvm::MDNode *CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
+ uint64_t LoopCount) {
+ if (!PGO.haveRegionCounts())
return nullptr;
- uint64_t LoopCount = Cnt.getCount();
- uint64_t CondCount = 0;
- bool Found = getStmtCount(Cond, CondCount);
- assert(Found && "missing expected loop condition count");
- (void)Found;
- if (CondCount == 0)
+ Optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
+ assert(CondCount.hasValue() && "missing expected loop condition count");
+ if (*CondCount == 0)
return nullptr;
- return createBranchWeights(LoopCount,
- std::max(CondCount, LoopCount) - LoopCount);
+ return createProfileWeights(LoopCount,
+ std::max(*CondCount, LoopCount) - LoopCount);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
index 431c850..de6f369 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
@@ -24,10 +24,8 @@
namespace clang {
namespace CodeGen {
-class RegionCounter;
-/// Per-function PGO state. This class should generally not be used directly,
-/// but instead through the CodeGenFunction and RegionCounter types.
+/// Per-function PGO state.
class CodeGenPGO {
private:
CodeGenModule &CGM;
@@ -62,37 +60,24 @@ public:
/// exits.
void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
- /// Indicate that the current region is never reached, and thus should have a
- /// counter value of zero. This is important so that subsequent regions can
- /// correctly track their parent counts.
- void setCurrentRegionUnreachable() { setCurrentRegionCount(0); }
-
/// Check if an execution count is known for a given statement. If so, return
/// true and put the value in Count; else return false.
- bool getStmtCount(const Stmt *S, uint64_t &Count) {
+ Optional<uint64_t> getStmtCount(const Stmt *S) {
if (!StmtCountMap)
- return false;
- llvm::DenseMap<const Stmt*, uint64_t>::const_iterator
- I = StmtCountMap->find(S);
+ return None;
+ auto I = StmtCountMap->find(S);
if (I == StmtCountMap->end())
- return false;
- Count = I->second;
- return true;
+ return None;
+ return I->second;
}
/// If the execution count for the current statement is known, record that
/// as the current count.
void setCurrentStmt(const Stmt *S) {
- uint64_t Count;
- if (getStmtCount(S, Count))
- setCurrentRegionCount(Count);
+ if (auto Count = getStmtCount(S))
+ setCurrentRegionCount(*Count);
}
- /// Calculate branch weights appropriate for PGO data
- llvm::MDNode *createBranchWeights(uint64_t TrueCount, uint64_t FalseCount);
- llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
- llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter &Cnt);
-
/// Check if we need to emit coverage mapping for a given declaration
void checkGlobalDecl(GlobalDecl GD);
/// Assign counters to regions and configure them for PGO of a given
@@ -117,110 +102,16 @@ private:
void emitCounterVariables();
void emitCounterRegionMapping(const Decl *D);
- /// Emit code to increment the counter at the given index
- void emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter);
+public:
+ void emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S);
- /// Return the region counter for the given statement. This should only be
- /// called on statements that have a dedicated counter.
- unsigned getRegionCounter(const Stmt *S) {
+ /// Return the region count for the counter at the given index.
+ uint64_t getRegionCount(const Stmt *S) {
if (!RegionCounterMap)
return 0;
- return (*RegionCounterMap)[S];
- }
-
- /// Return the region count for the counter at the given index.
- uint64_t getRegionCount(unsigned Counter) {
if (!haveRegionCounts())
return 0;
- return RegionCounts[Counter];
- }
-
- friend class RegionCounter;
-};
-
-/// A counter for a particular region. This is the primary interface through
-/// which clients manage PGO counters and their values.
-class RegionCounter {
- CodeGenPGO *PGO;
- unsigned Counter;
- uint64_t Count;
- uint64_t ParentCount;
- uint64_t RegionCount;
- int64_t Adjust;
-
- RegionCounter(CodeGenPGO &PGO, unsigned CounterIndex)
- : PGO(&PGO), Counter(CounterIndex), Count(PGO.getRegionCount(Counter)),
- ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
-
-public:
- RegionCounter(CodeGenPGO &PGO, const Stmt *S)
- : PGO(&PGO), Counter(PGO.getRegionCounter(S)),
- Count(PGO.getRegionCount(Counter)),
- ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
-
- /// Get the value of the counter. In most cases this is the number of times
- /// the region of the counter was entered, but for switch labels it's the
- /// number of direct jumps to that label.
- uint64_t getCount() const { return Count; }
-
- /// Get the value of the counter with adjustments applied. Adjustments occur
- /// when control enters or leaves the region abnormally; i.e., if there is a
- /// jump to a label within the region, or if the function can return from
- /// within the region. The adjusted count, then, is the value of the counter
- /// at the end of the region.
- uint64_t getAdjustedCount() const {
- return Count + Adjust;
- }
-
- /// Get the value of the counter in this region's parent, i.e., the region
- /// that was active when this region began. This is useful for deriving
- /// counts in implicitly counted regions, like the false case of a condition
- /// or the normal exits of a loop.
- uint64_t getParentCount() const { return ParentCount; }
-
- /// Activate the counter by emitting an increment and starting to track
- /// adjustments. If AddIncomingFallThrough is true, the current region count
- /// will be added to the counter for the purposes of tracking the region.
- void beginRegion(CGBuilderTy &Builder, bool AddIncomingFallThrough=false) {
- beginRegion(AddIncomingFallThrough);
- PGO->emitCounterIncrement(Builder, Counter);
- }
- void beginRegion(bool AddIncomingFallThrough=false) {
- RegionCount = Count;
- if (AddIncomingFallThrough)
- RegionCount += PGO->getCurrentRegionCount();
- PGO->setCurrentRegionCount(RegionCount);
- }
-
- /// For counters on boolean branches, begins tracking adjustments for the
- /// uncounted path.
- void beginElseRegion() {
- RegionCount = ParentCount - Count;
- PGO->setCurrentRegionCount(RegionCount);
- }
-
- /// Reset the current region count.
- void setCurrentRegionCount(uint64_t CurrentCount) {
- RegionCount = CurrentCount;
- PGO->setCurrentRegionCount(RegionCount);
- }
-
- /// Adjust for non-local control flow after emitting a subexpression or
- /// substatement. This must be called to account for constructs such as gotos,
- /// labels, and returns, so that we can ensure that our region's count is
- /// correct in the code that follows.
- void adjustForControlFlow() {
- Adjust += PGO->getCurrentRegionCount() - RegionCount;
- // Reset the region count in case this is called again later.
- RegionCount = PGO->getCurrentRegionCount();
- }
-
- /// Commit all adjustments to the current region. If the region is a loop,
- /// the LoopAdjust value should be the count of all the breaks and continues
- /// from the loop, to compensate for those counts being deducted from the
- /// adjustments for the body of the loop.
- void applyAdjustmentsToRegion(uint64_t LoopAdjust) {
- PGO->setCurrentRegionCount(ParentCount + Adjust + LoopAdjust);
+ return RegionCounts[(*RegionCounterMap)[S]];
}
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
index 67a9fbe..a4a8654 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -154,14 +154,16 @@ isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT,
static bool
isSafeToConvert(QualType T, CodeGenTypes &CGT,
llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) {
- T = T.getCanonicalType();
-
+ // Strip off atomic type sugar.
+ if (const auto *AT = T->getAs<AtomicType>())
+ T = AT->getValueType();
+
// If this is a record, check it.
- if (const RecordType *RT = dyn_cast<RecordType>(T))
+ if (const auto *RT = T->getAs<RecordType>())
return isSafeToConvert(RT->getDecl(), CGT, AlreadyChecked);
-
+
// If this is an array, check the elements, which are embedded inline.
- if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+ if (const auto *AT = CGT.getContext().getAsArrayType(T))
return isSafeToConvert(AT->getElementType(), CGT, AlreadyChecked);
// Otherwise, there is no concern about transforming this. We only care about
@@ -715,9 +717,16 @@ bool CodeGenTypes::isZeroInitializable(QualType T) {
// No need to check for member pointers when not compiling C++.
if (!Context.getLangOpts().CPlusPlus)
return true;
-
- T = Context.getBaseElementType(T);
-
+
+ if (const auto *AT = Context.getAsArrayType(T)) {
+ if (isa<IncompleteArrayType>(AT))
+ return true;
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
+ if (Context.getConstantArrayElementCount(CAT) == 0)
+ return true;
+ T = Context.getBaseElementType(T);
+ }
+
// Records are non-zero-initializable if they contain any
// non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) {
@@ -733,6 +742,6 @@ bool CodeGenTypes::isZeroInitializable(QualType T) {
return true;
}
-bool CodeGenTypes::isZeroInitializable(const CXXRecordDecl *RD) {
+bool CodeGenTypes::isZeroInitializable(const RecordDecl *RD) {
return getCGRecordLayout(RD).isZeroInitializable();
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
index 64c5799..1580e21 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
@@ -82,6 +82,9 @@ inline StructorType getFromCtorType(CXXCtorType T) {
return StructorType::Base;
case Ctor_Comdat:
llvm_unreachable("not expecting a COMDAT");
+ case Ctor_CopyingClosure:
+ case Ctor_DefaultClosure:
+ llvm_unreachable("not expecting a closure");
}
llvm_unreachable("not a CXXCtorType");
}
@@ -112,8 +115,8 @@ inline StructorType getFromDtorType(CXXDtorType T) {
llvm_unreachable("not a CXXDtorType");
}
-/// CodeGenTypes - This class organizes the cross-module state that is used
-/// while lowering AST types to LLVM types.
+/// This class organizes the cross-module state that is used while lowering
+/// AST types to LLVM types.
class CodeGenTypes {
CodeGenModule &CGM;
// Some of this stuff should probably be left on the CGM.
@@ -133,34 +136,32 @@ class CodeGenTypes {
/// types are never refined.
llvm::DenseMap<const ObjCInterfaceType*, llvm::Type *> InterfaceTypes;
- /// CGRecordLayouts - This maps llvm struct type with corresponding
- /// record layout info.
+ /// Maps clang struct type with corresponding record layout info.
llvm::DenseMap<const Type*, CGRecordLayout *> CGRecordLayouts;
- /// RecordDeclTypes - This contains the LLVM IR type for any converted
- /// RecordDecl.
+ /// Contains the LLVM IR type for any converted RecordDecl.
llvm::DenseMap<const Type*, llvm::StructType *> RecordDeclTypes;
- /// FunctionInfos - Hold memoized CGFunctionInfo results.
+ /// Hold memoized CGFunctionInfo results.
llvm::FoldingSet<CGFunctionInfo> FunctionInfos;
- /// RecordsBeingLaidOut - This set keeps track of records that we're currently
- /// converting to an IR type. For example, when converting:
+ /// This set keeps track of records that we're currently converting
+ /// to an IR type. For example, when converting:
/// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B'
/// types will be in this set.
llvm::SmallPtrSet<const Type*, 4> RecordsBeingLaidOut;
llvm::SmallPtrSet<const CGFunctionInfo*, 4> FunctionsBeingProcessed;
- /// SkippedLayout - True if we didn't layout a function due to a being inside
+ /// True if we didn't layout a function due to a being inside
/// a recursive struct conversion, set this to true.
bool SkippedLayout;
SmallVector<const RecordDecl *, 8> DeferredRecords;
private:
- /// TypeCache - This map keeps cache of llvm::Types
- /// and maps clang::Type to corresponding llvm::Type.
+ /// This map keeps cache of llvm::Types and maps clang::Type to
+ /// corresponding llvm::Type.
llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
public:
@@ -261,6 +262,8 @@ public:
const FunctionProtoType *type,
RequiredArgs required);
const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
+ const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
+ CXXCtorType CT);
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
@@ -305,7 +308,7 @@ public: // These are internal details of CGT that shouldn't be used externally.
/// IsZeroInitializable - Return whether a record type can be
/// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
- bool isZeroInitializable(const CXXRecordDecl *RD);
+ bool isZeroInitializable(const RecordDecl *RD);
bool isRecordLayoutComplete(const Type *Ty) const;
bool noRecordsBeingLaidOut() const {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
index 6f159d4..eca9159 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -15,6 +15,7 @@
#include "CodeGenFunction.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ProfileData/CoverageMapping.h"
#include "llvm/ProfileData/CoverageMappingReader.h"
#include "llvm/ProfileData/CoverageMappingWriter.h"
@@ -33,87 +34,50 @@ namespace {
/// \brief A region of source code that can be mapped to a counter.
class SourceMappingRegion {
-public:
- enum RegionFlags {
- /// \brief This region won't be emitted if it wasn't extended.
- /// This is useful so that we won't emit source ranges for single tokens
- /// that we don't really care that much about, like:
- /// the '(' token in #define MACRO (
- IgnoreIfNotExtended = 0x0001,
- };
-
-private:
- FileID File, MacroArgumentFile;
-
Counter Count;
- /// \brief A statement that initiated the count of Zero.
- ///
- /// This initiator statement is useful to prevent merging of unreachable
- /// regions with different statements that caused the counter to become
- /// unreachable.
- const Stmt *UnreachableInitiator;
-
- /// \brief A statement that separates certain mapping regions into groups.
- ///
- /// The group statement is sometimes useful when we are emitting the source
- /// regions not in their correct lexical order, e.g. the regions for the
- /// incrementation expression in the 'for' construct. By marking the regions
- /// in the incrementation expression with the group statement, we avoid the
- /// merging of the regions from the incrementation expression and the loop's
- /// body.
- const Stmt *Group;
-
/// \brief The region's starting location.
- SourceLocation LocStart;
+ Optional<SourceLocation> LocStart;
/// \brief The region's ending location.
- SourceLocation LocEnd, AlternativeLocEnd;
- unsigned Flags;
+ Optional<SourceLocation> LocEnd;
public:
- SourceMappingRegion(FileID File, FileID MacroArgumentFile, Counter Count,
- const Stmt *UnreachableInitiator, const Stmt *Group,
- SourceLocation LocStart, SourceLocation LocEnd,
- unsigned Flags = 0)
- : File(File), MacroArgumentFile(MacroArgumentFile), Count(Count),
- UnreachableInitiator(UnreachableInitiator), Group(Group),
- LocStart(LocStart), LocEnd(LocEnd), AlternativeLocEnd(LocStart),
- Flags(Flags) {}
+ SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
+ Optional<SourceLocation> LocEnd)
+ : Count(Count), LocStart(LocStart), LocEnd(LocEnd) {}
+
+ SourceMappingRegion(SourceMappingRegion &&Region)
+ : Count(std::move(Region.Count)), LocStart(std::move(Region.LocStart)),
+ LocEnd(std::move(Region.LocEnd)) {}
- const FileID &getFile() const { return File; }
+ SourceMappingRegion &operator=(SourceMappingRegion &&RHS) {
+ Count = std::move(RHS.Count);
+ LocStart = std::move(RHS.LocStart);
+ LocEnd = std::move(RHS.LocEnd);
+ return *this;
+ }
const Counter &getCounter() const { return Count; }
- const SourceLocation &getStartLoc() const { return LocStart; }
+ void setCounter(Counter C) { Count = C; }
- const SourceLocation &getEndLoc(const SourceManager &SM) const {
- if (SM.getFileID(LocEnd) != File)
- return AlternativeLocEnd;
- return LocEnd;
- }
+ bool hasStartLoc() const { return LocStart.hasValue(); }
- bool hasFlag(RegionFlags Flag) const { return (Flags & Flag) != 0; }
+ void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
- void setFlag(RegionFlags Flag) { Flags |= Flag; }
+ const SourceLocation &getStartLoc() const {
+ assert(LocStart && "Region has no start location");
+ return *LocStart;
+ }
- void clearFlag(RegionFlags Flag) { Flags &= ~Flag; }
+ bool hasEndLoc() const { return LocEnd.hasValue(); }
- /// \brief Return true if two regions can be merged together.
- bool isMergeable(SourceMappingRegion &R) {
- // FIXME: We allow merging regions with a gap in between them. Should we?
- return File == R.File && MacroArgumentFile == R.MacroArgumentFile &&
- Count == R.Count && UnreachableInitiator == R.UnreachableInitiator &&
- Group == R.Group;
- }
+ void setEndLoc(SourceLocation Loc) { LocEnd = Loc; }
- /// \brief A comparison that sorts such that mergeable regions are adjacent.
- friend bool operator<(const SourceMappingRegion &LHS,
- const SourceMappingRegion &RHS) {
- return std::tie(LHS.File, LHS.MacroArgumentFile, LHS.Count,
- LHS.UnreachableInitiator, LHS.Group) <
- std::tie(RHS.File, RHS.MacroArgumentFile, RHS.Count,
- RHS.UnreachableInitiator, RHS.Group);
+ const SourceLocation &getEndLoc() const {
+ assert(LocEnd && "Region has no end location");
+ return *LocEnd;
}
};
@@ -126,26 +90,11 @@ public:
const LangOptions &LangOpts;
private:
- struct FileInfo {
- /// \brief The file id that will be used by the coverage mapping system.
- unsigned CovMappingFileID;
- const FileEntry *Entry;
-
- FileInfo(unsigned CovMappingFileID, const FileEntry *Entry)
- : CovMappingFileID(CovMappingFileID), Entry(Entry) {}
- };
-
- /// \brief This mapping maps clang's FileIDs to file ids used
- /// by the coverage mapping system and clang's file entries.
- llvm::SmallDenseMap<FileID, FileInfo, 8> FileIDMapping;
+ /// \brief Map of clang's FileIDs to IDs used for coverage mapping.
+ llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
+ FileIDMapping;
public:
- /// \brief The statement that corresponds to the current source group.
- const Stmt *CurrentSourceGroup;
-
- /// \brief The statement the initiated the current unreachable region.
- const Stmt *CurrentUnreachableRegionInitiator;
-
/// \brief The coverage mapping regions for this function
llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
/// \brief The source mapping regions for this function.
@@ -153,60 +102,104 @@ public:
CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
const LangOptions &LangOpts)
- : CVM(CVM), SM(SM), LangOpts(LangOpts),
- CurrentSourceGroup(nullptr),
- CurrentUnreachableRegionInitiator(nullptr) {}
+ : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
/// \brief Return the precise end location for the given token.
SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
- return Lexer::getLocForEndOfToken(SM.getSpellingLoc(Loc), 0, SM, LangOpts);
+ // We avoid getLocForEndOfToken here, because it doesn't do what we want for
+ // macro locations, which we just treat as expanded files.
+ unsigned TokLen =
+ Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
+ return Loc.getLocWithOffset(TokLen);
}
- /// \brief Create the mapping that maps from the function's file ids to
- /// the indices for the translation unit's filenames.
- void createFileIDMapping(SmallVectorImpl<unsigned> &Mapping) {
- Mapping.resize(FileIDMapping.size(), 0);
- for (const auto &I : FileIDMapping)
- Mapping[I.second.CovMappingFileID] = CVM.getFileID(I.second.Entry);
+ /// \brief Return the start location of an included file or expanded macro.
+ SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
+ if (Loc.isMacroID())
+ return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
+ return SM.getLocForStartOfFile(SM.getFileID(Loc));
}
- /// \brief Get the coverage mapping file id that corresponds to the given
- /// clang file id. If such file id doesn't exist, it gets added to the
- /// mapping that maps from clang's file ids to coverage mapping file ids.
- /// Return true if there was an error getting the coverage mapping file id.
- /// An example of an when this function fails is when the region tries
- /// to get a coverage file id for a location in a built-in macro.
- bool getCoverageFileID(SourceLocation LocStart, FileID File,
- FileID SpellingFile, unsigned &Result) {
- auto Mapping = FileIDMapping.find(File);
- if (Mapping != FileIDMapping.end()) {
- Result = Mapping->second.CovMappingFileID;
- return false;
- }
+ /// \brief Return the end location of an included file or expanded macro.
+ SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
+ if (Loc.isMacroID())
+ return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
+ SM.getFileOffset(Loc));
+ return SM.getLocForEndOfFile(SM.getFileID(Loc));
+ }
+
+ /// \brief Find out where the current file is included or macro is expanded.
+ SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
+ return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).first
+ : SM.getIncludeLoc(SM.getFileID(Loc));
+ }
- auto Entry = SM.getFileEntryForID(SpellingFile);
- if (!Entry)
- return true;
+ /// \brief Return true if \c Loc is a location in a built-in macro.
+ bool isInBuiltin(SourceLocation Loc) {
+ return strcmp(SM.getBufferName(SM.getSpellingLoc(Loc)), "<built-in>") == 0;
+ }
+
+ /// \brief Get the start of \c S ignoring macro arguments and builtin macros.
+ SourceLocation getStart(const Stmt *S) {
+ SourceLocation Loc = S->getLocStart();
+ while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
+ Loc = SM.getImmediateExpansionRange(Loc).first;
+ return Loc;
+ }
- Result = FileIDMapping.size();
- FileIDMapping.insert(std::make_pair(File, FileInfo(Result, Entry)));
- createFileExpansionRegion(LocStart, File);
- return false;
+ /// \brief Get the end of \c S ignoring macro arguments and builtin macros.
+ SourceLocation getEnd(const Stmt *S) {
+ SourceLocation Loc = S->getLocEnd();
+ while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
+ Loc = SM.getImmediateExpansionRange(Loc).first;
+ return getPreciseTokenLocEnd(Loc);
}
- /// \brief Get the coverage mapping file id that corresponds to the given
- /// clang file id.
- /// Return true if there was an error getting the coverage mapping file id.
- bool getExistingCoverageFileID(FileID File, unsigned &Result) {
- // Make sure that the file is valid.
- if (File.isInvalid())
- return true;
- auto Mapping = FileIDMapping.find(File);
- if (Mapping != FileIDMapping.end()) {
- Result = Mapping->second.CovMappingFileID;
- return false;
+ /// \brief Find the set of files we have regions for and assign IDs
+ ///
+ /// Fills \c Mapping with the virtual file mapping needed to write out
+ /// coverage and collects the necessary file information to emit source and
+ /// expansion regions.
+ void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
+ FileIDMapping.clear();
+
+ SmallVector<FileID, 8> Visited;
+ SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
+ for (const auto &Region : SourceRegions) {
+ SourceLocation Loc = Region.getStartLoc();
+ FileID File = SM.getFileID(Loc);
+ if (std::find(Visited.begin(), Visited.end(), File) != Visited.end())
+ continue;
+ Visited.push_back(File);
+
+ unsigned Depth = 0;
+ for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
+ !Parent.isInvalid(); Parent = getIncludeOrExpansionLoc(Parent))
+ ++Depth;
+ FileLocs.push_back(std::make_pair(Loc, Depth));
+ }
+ std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second());
+
+ for (const auto &FL : FileLocs) {
+ SourceLocation Loc = FL.first;
+ FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
+ auto Entry = SM.getFileEntryForID(SpellingFile);
+ if (!Entry)
+ continue;
+
+ FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
+ Mapping.push_back(CVM.getFileID(Entry));
}
- return true;
+ }
+
+ /// \brief Get the coverage mapping file ID for \c Loc.
+ ///
+ /// If such file id doesn't exist, return None.
+ Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
+ auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
+ if (Mapping != FileIDMapping.end())
+ return Mapping->second.first;
+ return None;
}
/// \brief Return true if the given clang's file id has a corresponding
@@ -235,154 +228,83 @@ public:
for (const auto &I : SkippedRanges) {
auto LocStart = I.getBegin();
auto LocEnd = I.getEnd();
- auto FileStart = SM.getFileID(LocStart);
- if (!hasExistingCoverageFileID(FileStart))
- continue;
- auto ActualFileStart = SM.getDecomposedSpellingLoc(LocStart).first;
- if (ActualFileStart != SM.getDecomposedSpellingLoc(LocEnd).first)
- // Ignore regions that span across multiple files.
- continue;
+ assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
+ "region spans multiple files");
- unsigned CovFileID;
- if (getCoverageFileID(LocStart, FileStart, ActualFileStart, CovFileID))
+ auto CovFileID = getCoverageFileID(LocStart);
+ if (!CovFileID)
continue;
unsigned LineStart = SM.getSpellingLineNumber(LocStart);
unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
- CounterMappingRegion Region(Counter(), CovFileID, LineStart, ColumnStart,
- LineEnd, ColumnEnd, false,
- CounterMappingRegion::SkippedRegion);
+ auto Region = CounterMappingRegion::makeSkipped(
+ *CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd);
// Make sure that we only collect the regions that are inside
// the souce code of this function.
- if (Region.LineStart >= FileLineRanges[CovFileID].first &&
- Region.LineEnd <= FileLineRanges[CovFileID].second)
+ if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
+ Region.LineEnd <= FileLineRanges[*CovFileID].second)
MappingRegions.push_back(Region);
}
}
- /// \brief Create a mapping region that correponds to an expansion of
- /// a macro or an embedded include.
- void createFileExpansionRegion(SourceLocation Loc, FileID ExpandedFile) {
- SourceLocation LocStart;
- if (Loc.isMacroID())
- LocStart = SM.getImmediateExpansionRange(Loc).first;
- else {
- LocStart = SM.getIncludeLoc(ExpandedFile);
- if (LocStart.isInvalid())
- return; // This file has no expansion region.
- }
-
- auto File = SM.getFileID(LocStart);
- auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
- unsigned CovFileID, ExpandedFileID;
- if (getExistingCoverageFileID(ExpandedFile, ExpandedFileID))
- return;
- if (getCoverageFileID(LocStart, File, SpellingFile, CovFileID))
- return;
- unsigned LineStart = SM.getSpellingLineNumber(LocStart);
- unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
- unsigned LineEnd = LineStart;
- // Compute the end column manually as Lexer::getLocForEndOfToken doesn't
- // give the correct result in all cases.
- unsigned ColumnEnd =
- ColumnStart +
- Lexer::MeasureTokenLength(SM.getSpellingLoc(LocStart), SM, LangOpts);
-
- MappingRegions.push_back(CounterMappingRegion(
- Counter(), CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
- false, CounterMappingRegion::ExpansionRegion));
- MappingRegions.back().ExpandedFileID = ExpandedFileID;
- }
-
- /// \brief Enter a source region group that is identified by the given
- /// statement.
- /// It's not possible to enter a group when there is already
- /// another group present.
- void beginSourceRegionGroup(const Stmt *Group) {
- assert(!CurrentSourceGroup);
- CurrentSourceGroup = Group;
- }
-
- /// \brief Exit the current source region group.
- void endSourceRegionGroup() { CurrentSourceGroup = nullptr; }
-
- /// \brief Associate a counter with a given source code range.
- void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
- Counter Count, const Stmt *UnreachableInitiator,
- const Stmt *SourceGroup, unsigned Flags = 0,
- FileID MacroArgumentFile = FileID()) {
- if (SM.isMacroArgExpansion(LocStart)) {
- // Map the code range with the macro argument's value.
- mapSourceCodeRange(SM.getImmediateSpellingLoc(LocStart),
- SM.getImmediateSpellingLoc(LocEnd), Count,
- UnreachableInitiator, SourceGroup, Flags,
- SM.getFileID(LocStart));
- // Map the code range where the macro argument is referenced.
- SourceLocation RefLocStart(SM.getImmediateExpansionRange(LocStart).first);
- SourceLocation RefLocEnd(RefLocStart);
- if (SM.isMacroArgExpansion(RefLocStart))
- mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
- SourceGroup, 0, SM.getFileID(RefLocStart));
- else
- mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
- SourceGroup);
- return;
- }
- auto File = SM.getFileID(LocStart);
- // Make sure that the file id is valid.
- if (File.isInvalid())
- return;
- SourceRegions.emplace_back(File, MacroArgumentFile, Count,
- UnreachableInitiator, SourceGroup, LocStart,
- LocEnd, Flags);
- }
-
- void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
- Counter Count, unsigned Flags = 0) {
- mapSourceCodeRange(LocStart, LocEnd, Count,
- CurrentUnreachableRegionInitiator, CurrentSourceGroup,
- Flags);
- }
-
/// \brief Generate the coverage counter mapping regions from collected
/// source regions.
void emitSourceRegions() {
- std::sort(SourceRegions.begin(), SourceRegions.end());
-
- for (auto I = SourceRegions.begin(), E = SourceRegions.end(); I != E; ++I) {
- // Keep the original start location of this region.
- SourceLocation LocStart = I->getStartLoc();
- SourceLocation LocEnd = I->getEndLoc(SM);
-
- bool Ignore = I->hasFlag(SourceMappingRegion::IgnoreIfNotExtended);
- // We need to handle mergeable regions together.
- for (auto Next = I + 1; Next != E && Next->isMergeable(*I); ++Next) {
- ++I;
- LocStart = std::min(LocStart, I->getStartLoc());
- LocEnd = std::max(LocEnd, I->getEndLoc(SM));
- // FIXME: Should we && together the Ignore flag of multiple regions?
- Ignore = false;
- }
- if (Ignore)
+ for (const auto &Region : SourceRegions) {
+ assert(Region.hasEndLoc() && "incomplete region");
+
+ SourceLocation LocStart = Region.getStartLoc();
+ assert(!SM.getFileID(LocStart).isInvalid() && "region in invalid file");
+
+ auto CovFileID = getCoverageFileID(LocStart);
+ // Ignore regions that don't have a file, such as builtin macros.
+ if (!CovFileID)
continue;
+ SourceLocation LocEnd = Region.getEndLoc();
+ assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
+ "region spans multiple files");
+
// Find the spilling locations for the mapping region.
- LocEnd = getPreciseTokenLocEnd(LocEnd);
unsigned LineStart = SM.getSpellingLineNumber(LocStart);
unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
- auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
- unsigned CovFileID;
- if (getCoverageFileID(LocStart, I->getFile(), SpellingFile, CovFileID))
+ assert(LineStart <= LineEnd && "region start and end out of order");
+ MappingRegions.push_back(CounterMappingRegion::makeRegion(
+ Region.getCounter(), *CovFileID, LineStart, ColumnStart, LineEnd,
+ ColumnEnd));
+ }
+ }
+
+ /// \brief Generate expansion regions for each virtual file we've seen.
+ void emitExpansionRegions() {
+ for (const auto &FM : FileIDMapping) {
+ SourceLocation ExpandedLoc = FM.second.second;
+ SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
+ if (ParentLoc.isInvalid())
+ continue;
+
+ auto ParentFileID = getCoverageFileID(ParentLoc);
+ if (!ParentFileID)
continue;
+ auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
+ assert(ExpandedFileID && "expansion in uncovered file");
+
+ SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
+ assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
+ "region spans multiple files");
+
+ unsigned LineStart = SM.getSpellingLineNumber(ParentLoc);
+ unsigned ColumnStart = SM.getSpellingColumnNumber(ParentLoc);
+ unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
+ unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
- assert(LineStart <= LineEnd);
- MappingRegions.push_back(CounterMappingRegion(
- I->getCounter(), CovFileID, LineStart, ColumnStart, LineEnd,
- ColumnEnd, false, CounterMappingRegion::CodeRegion));
+ MappingRegions.push_back(CounterMappingRegion::makeExpansion(
+ *ParentFileID, *ExpandedFileID, LineStart, ColumnStart, LineEnd,
+ ColumnEnd));
}
}
};
@@ -398,14 +320,14 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
if (!D->hasBody())
return;
auto Body = D->getBody();
- mapSourceCodeRange(Body->getLocStart(), Body->getLocEnd(), Counter());
+ SourceRegions.emplace_back(Counter(), getStart(Body), getEnd(Body));
}
/// \brief Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
- emitSourceRegions();
SmallVector<unsigned, 16> FileIDMapping;
- createFileIDMapping(FileIDMapping);
+ gatherFileIDs(FileIDMapping);
+ emitSourceRegions();
CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
Writer.write(OS);
@@ -420,136 +342,216 @@ struct CounterCoverageMappingBuilder
/// \brief The map of statements to count values.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
- Counter CurrentRegionCount;
+ /// \brief A stack of currently live regions.
+ std::vector<SourceMappingRegion> RegionStack;
CounterExpressionBuilder Builder;
- /// \brief Return a counter that represents the
- /// expression that subracts rhs from lhs.
+ /// \brief A location in the most recently visited file or macro.
+ ///
+ /// This is used to adjust the active source regions appropriately when
+ /// expressions cross file or macro boundaries.
+ SourceLocation MostRecentLocation;
+
+ /// \brief Return a counter for the subtraction of \c RHS from \c LHS
Counter subtractCounters(Counter LHS, Counter RHS) {
return Builder.subtract(LHS, RHS);
}
- /// \brief Return a counter that represents the
- /// the exression that adds lhs and rhs.
+ /// \brief Return a counter for the sum of \c LHS and \c RHS.
Counter addCounters(Counter LHS, Counter RHS) {
return Builder.add(LHS, RHS);
}
+ Counter addCounters(Counter C1, Counter C2, Counter C3) {
+ return addCounters(addCounters(C1, C2), C3);
+ }
+
+ Counter addCounters(Counter C1, Counter C2, Counter C3, Counter C4) {
+ return addCounters(addCounters(C1, C2, C3), C4);
+ }
+
/// \brief Return the region counter for the given statement.
+ ///
/// This should only be called on statements that have a dedicated counter.
- unsigned getRegionCounter(const Stmt *S) { return CounterMap[S]; }
+ Counter getRegionCounter(const Stmt *S) {
+ return Counter::getCounter(CounterMap[S]);
+ }
+
+ /// \brief Push a region onto the stack.
+ ///
+ /// Returns the index on the stack where the region was pushed. This can be
+ /// used with popRegions to exit a "scope", ending the region that was pushed.
+ size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
+ Optional<SourceLocation> EndLoc = None) {
+ if (StartLoc)
+ MostRecentLocation = *StartLoc;
+ RegionStack.emplace_back(Count, StartLoc, EndLoc);
- /// \brief Return the region count for the counter at the given index.
- Counter getRegionCount(unsigned CounterId) {
- return Counter::getCounter(CounterId);
+ return RegionStack.size() - 1;
}
- /// \brief Return the counter value of the current region.
- Counter getCurrentRegionCount() { return CurrentRegionCount; }
+ /// \brief Pop regions from the stack into the function's list of regions.
+ ///
+ /// Adds all regions from \c ParentIndex to the top of the stack to the
+ /// function's \c SourceRegions.
+ void popRegions(size_t ParentIndex) {
+ assert(RegionStack.size() >= ParentIndex && "parent not in stack");
+ while (RegionStack.size() > ParentIndex) {
+ SourceMappingRegion &Region = RegionStack.back();
+ if (Region.hasStartLoc()) {
+ SourceLocation StartLoc = Region.getStartLoc();
+ SourceLocation EndLoc = Region.hasEndLoc()
+ ? Region.getEndLoc()
+ : RegionStack[ParentIndex].getEndLoc();
+ while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
+ // The region ends in a nested file or macro expansion. Create a
+ // separate region for each expansion.
+ SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
+ assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
+
+ SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+
+ EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
+ assert(!EndLoc.isInvalid() &&
+ "File exit was not handled before popRegions");
+ }
+ Region.setEndLoc(EndLoc);
+
+ MostRecentLocation = EndLoc;
+ // If this region happens to span an entire expansion, we need to make
+ // sure we don't overlap the parent region with it.
+ if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
+ EndLoc == getEndOfFileOrMacro(EndLoc))
+ MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
+
+ assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc));
+ SourceRegions.push_back(std::move(Region));
+ }
+ RegionStack.pop_back();
+ }
+ }
- /// \brief Set the counter value for the current region.
- /// This is used to keep track of changes to the most recent counter
- /// from control flow and non-local exits.
- void setCurrentRegionCount(Counter Count) {
- CurrentRegionCount = Count;
- CurrentUnreachableRegionInitiator = nullptr;
+ /// \brief Return the currently active region.
+ SourceMappingRegion &getRegion() {
+ assert(!RegionStack.empty() && "statement has no region");
+ return RegionStack.back();
}
- /// \brief Indicate that the current region is never reached,
- /// and thus should have a counter value of zero.
- /// This is important so that subsequent regions can correctly track
- /// their parent counts.
- void setCurrentRegionUnreachable(const Stmt *Initiator) {
- CurrentRegionCount = Counter::getZero();
- CurrentUnreachableRegionInitiator = Initiator;
+ /// \brief Propagate counts through the children of \c S.
+ Counter propagateCounts(Counter TopCount, const Stmt *S) {
+ size_t Index = pushRegion(TopCount, getStart(S), getEnd(S));
+ Visit(S);
+ Counter ExitCount = getRegion().getCounter();
+ popRegions(Index);
+ return ExitCount;
}
- /// \brief A counter for a particular region.
- /// This is the primary interface through
- /// which the coverage mapping builder manages counters and their values.
- class RegionMapper {
- CounterCoverageMappingBuilder &Mapping;
- Counter Count;
- Counter ParentCount;
- Counter RegionCount;
- Counter Adjust;
-
- public:
- RegionMapper(CounterCoverageMappingBuilder *Mapper, const Stmt *S)
- : Mapping(*Mapper),
- Count(Mapper->getRegionCount(Mapper->getRegionCounter(S))),
- ParentCount(Mapper->getCurrentRegionCount()) {}
-
- /// Get the value of the counter. In most cases this is the number of times
- /// the region of the counter was entered, but for switch labels it's the
- /// number of direct jumps to that label.
- Counter getCount() const { return Count; }
-
- /// Get the value of the counter with adjustments applied. Adjustments occur
- /// when control enters or leaves the region abnormally; i.e., if there is a
- /// jump to a label within the region, or if the function can return from
- /// within the region. The adjusted count, then, is the value of the counter
- /// at the end of the region.
- Counter getAdjustedCount() const {
- return Mapping.addCounters(Count, Adjust);
- }
+ /// \brief Adjust the most recently visited location to \c EndLoc.
+ ///
+ /// This should be used after visiting any statements in non-source order.
+ void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
+ MostRecentLocation = EndLoc;
+ // Avoid adding duplicate regions if we have a completed region on the top
+ // of the stack and are adjusting to the end of a virtual file.
+ if (getRegion().hasEndLoc() &&
+ MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation))
+ MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
+ }
+
+ /// \brief Check whether \c Loc is included or expanded from \c Parent.
+ bool isNestedIn(SourceLocation Loc, FileID Parent) {
+ do {
+ Loc = getIncludeOrExpansionLoc(Loc);
+ if (Loc.isInvalid())
+ return false;
+ } while (!SM.isInFileID(Loc, Parent));
+ return true;
+ }
- /// Get the value of the counter in this region's parent, i.e., the region
- /// that was active when this region began. This is useful for deriving
- /// counts in implicitly counted regions, like the false case of a condition
- /// or the normal exits of a loop.
- Counter getParentCount() const { return ParentCount; }
-
- /// Activate the counter by emitting an increment and starting to track
- /// adjustments. If AddIncomingFallThrough is true, the current region count
- /// will be added to the counter for the purposes of tracking the region.
- void beginRegion(bool AddIncomingFallThrough = false) {
- RegionCount = Count;
- if (AddIncomingFallThrough)
- RegionCount =
- Mapping.addCounters(RegionCount, Mapping.getCurrentRegionCount());
- Mapping.setCurrentRegionCount(RegionCount);
- }
+ /// \brief Adjust regions and state when \c NewLoc exits a file.
+ ///
+ /// If moving from our most recently tracked location to \c NewLoc exits any
+ /// files, this adjusts our current region stack and creates the file regions
+ /// for the exited file.
+ void handleFileExit(SourceLocation NewLoc) {
+ if (NewLoc.isInvalid() ||
+ SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
+ return;
- /// For counters on boolean branches, begins tracking adjustments for the
- /// uncounted path.
- void beginElseRegion() {
- RegionCount = Mapping.subtractCounters(ParentCount, Count);
- Mapping.setCurrentRegionCount(RegionCount);
+ // If NewLoc is not in a file that contains MostRecentLocation, walk up to
+ // find the common ancestor.
+ SourceLocation LCA = NewLoc;
+ FileID ParentFile = SM.getFileID(LCA);
+ while (!isNestedIn(MostRecentLocation, ParentFile)) {
+ LCA = getIncludeOrExpansionLoc(LCA);
+ if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
+ // Since there isn't a common ancestor, no file was exited. We just need
+ // to adjust our location to the new file.
+ MostRecentLocation = NewLoc;
+ return;
+ }
+ ParentFile = SM.getFileID(LCA);
}
- /// Reset the current region count.
- void setCurrentRegionCount(Counter CurrentCount) {
- RegionCount = CurrentCount;
- Mapping.setCurrentRegionCount(RegionCount);
- }
+ llvm::SmallSet<SourceLocation, 8> StartLocs;
+ Optional<Counter> ParentCounter;
+ for (auto I = RegionStack.rbegin(), E = RegionStack.rend(); I != E; ++I) {
+ if (!I->hasStartLoc())
+ continue;
+ SourceLocation Loc = I->getStartLoc();
+ if (!isNestedIn(Loc, ParentFile)) {
+ ParentCounter = I->getCounter();
+ break;
+ }
- /// Adjust for non-local control flow after emitting a subexpression or
- /// substatement. This must be called to account for constructs such as
- /// gotos,
- /// labels, and returns, so that we can ensure that our region's count is
- /// correct in the code that follows.
- void adjustForControlFlow() {
- Adjust = Mapping.addCounters(
- Adjust, Mapping.subtractCounters(Mapping.getCurrentRegionCount(),
- RegionCount));
- // Reset the region count in case this is called again later.
- RegionCount = Mapping.getCurrentRegionCount();
+ while (!SM.isInFileID(Loc, ParentFile)) {
+ // The most nested region for each start location is the one with the
+ // correct count. We avoid creating redundant regions by stopping once
+ // we've seen this region.
+ if (StartLocs.insert(Loc).second)
+ SourceRegions.emplace_back(I->getCounter(), Loc,
+ getEndOfFileOrMacro(Loc));
+ Loc = getIncludeOrExpansionLoc(Loc);
+ }
+ I->setStartLoc(getPreciseTokenLocEnd(Loc));
}
- /// Commit all adjustments to the current region. If the region is a loop,
- /// the LoopAdjust value should be the count of all the breaks and continues
- /// from the loop, to compensate for those counts being deducted from the
- /// adjustments for the body of the loop.
- void applyAdjustmentsToRegion() {
- Mapping.setCurrentRegionCount(Mapping.addCounters(ParentCount, Adjust));
- }
- void applyAdjustmentsToRegion(Counter LoopAdjust) {
- Mapping.setCurrentRegionCount(Mapping.addCounters(
- Mapping.addCounters(ParentCount, Adjust), LoopAdjust));
+ if (ParentCounter) {
+ // If the file is contained completely by another region and doesn't
+ // immediately start its own region, the whole file gets a region
+ // corresponding to the parent.
+ SourceLocation Loc = MostRecentLocation;
+ while (isNestedIn(Loc, ParentFile)) {
+ SourceLocation FileStart = getStartOfFileOrMacro(Loc);
+ if (StartLocs.insert(FileStart).second)
+ SourceRegions.emplace_back(*ParentCounter, FileStart,
+ getEndOfFileOrMacro(Loc));
+ Loc = getIncludeOrExpansionLoc(Loc);
+ }
}
- };
+
+ MostRecentLocation = NewLoc;
+ }
+
+ /// \brief Ensure that \c S is included in the current region.
+ void extendRegion(const Stmt *S) {
+ SourceMappingRegion &Region = getRegion();
+ SourceLocation StartLoc = getStart(S);
+
+ handleFileExit(StartLoc);
+ if (!Region.hasStartLoc())
+ Region.setStartLoc(StartLoc);
+ }
+
+ /// \brief Mark \c S as a terminator, starting a zero region.
+ void terminateRegion(const Stmt *S) {
+ extendRegion(S);
+ SourceMappingRegion &Region = getRegion();
+ if (!Region.hasEndLoc())
+ Region.setEndLoc(getEnd(S));
+ pushRegion(Counter::getZero());
+ }
/// \brief Keep counts of breaks and continues inside loops.
struct BreakContinue {
@@ -566,437 +568,320 @@ struct CounterCoverageMappingBuilder
/// \brief Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
- emitSourceRegions();
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
- createFileIDMapping(VirtualFileMapping);
+ gatherFileIDs(VirtualFileMapping);
+ emitSourceRegions();
+ emitExpansionRegions();
gatherSkippedRegions();
- CoverageMappingWriter Writer(
- VirtualFileMapping, Builder.getExpressions(), MappingRegions);
+ CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
+ MappingRegions);
Writer.write(OS);
}
- /// \brief Associate the source code range with the current region count.
- void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
- unsigned Flags = 0) {
- CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocEnd,
- CurrentRegionCount, Flags);
- }
-
- void mapSourceCodeRange(SourceLocation LocStart) {
- CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocStart,
- CurrentRegionCount);
- }
-
- /// \brief Associate the source range of a token with the current region
- /// count.
- /// Ignore the source range for this token if it produces a distinct
- /// mapping region with no other source ranges.
- void mapToken(SourceLocation LocStart) {
- CoverageMappingBuilder::mapSourceCodeRange(
- LocStart, LocStart, CurrentRegionCount,
- SourceMappingRegion::IgnoreIfNotExtended);
- }
-
void VisitStmt(const Stmt *S) {
- mapSourceCodeRange(S->getLocStart());
- for (Stmt::const_child_range I = S->children(); I; ++I) {
- if (*I)
- this->Visit(*I);
- }
+ if (!S->getLocStart().isInvalid())
+ extendRegion(S);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ this->Visit(Child);
+ handleFileExit(getEnd(S));
}
void VisitDecl(const Decl *D) {
- if (!D->hasBody())
- return;
- // Counter tracks entry to the function body.
- auto Body = D->getBody();
- RegionMapper Cnt(this, Body);
- Cnt.beginRegion();
- Visit(Body);
- }
-
- void VisitDeclStmt(const DeclStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- for (Stmt::const_child_range I = static_cast<const Stmt *>(S)->children();
- I; ++I) {
- if (*I)
- this->Visit(*I);
- }
- }
-
- void VisitCompoundStmt(const CompoundStmt *S) {
- mapSourceCodeRange(S->getLBracLoc());
- mapSourceCodeRange(S->getRBracLoc());
- for (Stmt::const_child_range I = S->children(); I; ++I) {
- if (*I)
- this->Visit(*I);
- }
+ Stmt *Body = D->getBody();
+ propagateCounts(getRegionCounter(Body), Body);
}
void VisitReturnStmt(const ReturnStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
if (S->getRetValue())
Visit(S->getRetValue());
- setCurrentRegionUnreachable(S);
+ terminateRegion(S);
}
- void VisitGotoStmt(const GotoStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- mapToken(S->getLabelLoc());
- setCurrentRegionUnreachable(S);
+ void VisitCXXThrowExpr(const CXXThrowExpr *E) {
+ extendRegion(E);
+ if (E->getSubExpr())
+ Visit(E->getSubExpr());
+ terminateRegion(E);
}
+ void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
+
void VisitLabelStmt(const LabelStmt *S) {
- // Counter tracks the block following the label.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion();
- mapSourceCodeRange(S->getLocStart());
- // Can't map the ':' token as its location isn't known.
+ SourceLocation Start = getStart(S);
+ // We can't extendRegion here or we risk overlapping with our new region.
+ handleFileExit(Start);
+ pushRegion(getRegionCounter(S), Start);
Visit(S->getSubStmt());
}
void VisitBreakStmt(const BreakStmt *S) {
- mapSourceCodeRange(S->getLocStart());
assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
BreakContinueStack.back().BreakCount = addCounters(
- BreakContinueStack.back().BreakCount, getCurrentRegionCount());
- setCurrentRegionUnreachable(S);
+ BreakContinueStack.back().BreakCount, getRegion().getCounter());
+ terminateRegion(S);
}
void VisitContinueStmt(const ContinueStmt *S) {
- mapSourceCodeRange(S->getLocStart());
assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
BreakContinueStack.back().ContinueCount = addCounters(
- BreakContinueStack.back().ContinueCount, getCurrentRegionCount());
- setCurrentRegionUnreachable(S);
+ BreakContinueStack.back().ContinueCount, getRegion().getCounter());
+ terminateRegion(S);
}
void VisitWhileStmt(const WhileStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- // Counter tracks the body of the loop.
- RegionMapper Cnt(this, S);
+ extendRegion(S);
+
+ Counter ParentCount = getRegion().getCounter();
+ Counter BodyCount = getRegionCounter(S);
+
+ // Handle the body first so that we can get the backedge count.
BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first so the break/continue adjustments can be
- // included when visiting the condition.
- Cnt.beginRegion();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
-
- // ...then go back and propagate counts through the condition. The count
- // at the start of the condition is the sum of the incoming edges,
- // the backedge from the end of the loop body, and the edges from
- // continue statements.
+ extendRegion(S->getBody());
+ Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
- Cnt.setCurrentRegionCount(
- addCounters(Cnt.getParentCount(),
- addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
- beginSourceRegionGroup(S->getCond());
- Visit(S->getCond());
- endSourceRegionGroup();
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+
+ // Go back to handle the condition.
+ Counter CondCount =
+ addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+ propagateCounts(CondCount, S->getCond());
+ adjustForOutOfOrderTraversal(getEnd(S));
+
+ Counter OutCount =
+ addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitDoStmt(const DoStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- // Counter tracks the body of the loop.
- RegionMapper Cnt(this, S);
- BreakContinueStack.push_back(BreakContinue());
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
+ extendRegion(S);
+
+ Counter ParentCount = getRegion().getCounter();
+ Counter BodyCount = getRegionCounter(S);
+ BreakContinueStack.push_back(BreakContinue());
+ extendRegion(S->getBody());
+ Counter BackedgeCount =
+ propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
- // The count at the start of the condition is equal to the count at the
- // end of the body. The adjusted count does not include either the
- // fall-through count coming into the loop or the continue count, so add
- // both of those separately. This is coincidentally the same equation as
- // with while loops but for different reasons.
- Cnt.setCurrentRegionCount(
- addCounters(Cnt.getParentCount(),
- addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
- Visit(S->getCond());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+
+ Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
+ propagateCounts(CondCount, S->getCond());
+
+ Counter OutCount =
+ addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitForStmt(const ForStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
if (S->getInit())
Visit(S->getInit());
- // Counter tracks the body of the loop.
- RegionMapper Cnt(this, S);
+ Counter ParentCount = getRegion().getCounter();
+ Counter BodyCount = getRegionCounter(S);
+
+ // Handle the body first so that we can get the backedge count.
BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first. (This is basically the same as a while
- // loop; see further comments in VisitWhileStmt.)
- Cnt.beginRegion();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
+ extendRegion(S->getBody());
+ Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
+ BreakContinue BC = BreakContinueStack.pop_back_val();
// The increment is essentially part of the body but it needs to include
// the count for all the continue statements.
- if (S->getInc()) {
- Cnt.setCurrentRegionCount(addCounters(
- getCurrentRegionCount(), BreakContinueStack.back().ContinueCount));
- beginSourceRegionGroup(S->getInc());
- Visit(S->getInc());
- endSourceRegionGroup();
- Cnt.adjustForControlFlow();
+ if (const Stmt *Inc = S->getInc())
+ propagateCounts(addCounters(BackedgeCount, BC.ContinueCount), Inc);
+
+ // Go back to handle the condition.
+ Counter CondCount =
+ addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+ if (const Expr *Cond = S->getCond()) {
+ propagateCounts(CondCount, Cond);
+ adjustForOutOfOrderTraversal(getEnd(S));
}
- BreakContinue BC = BreakContinueStack.pop_back_val();
-
- // ...then go back and propagate counts through the condition.
- if (S->getCond()) {
- Cnt.setCurrentRegionCount(
- addCounters(addCounters(Cnt.getParentCount(), Cnt.getAdjustedCount()),
- BC.ContinueCount));
- beginSourceRegionGroup(S->getCond());
- Visit(S->getCond());
- endSourceRegionGroup();
- Cnt.adjustForControlFlow();
- }
- Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+ Counter OutCount =
+ addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
+ Visit(S->getLoopVarStmt());
Visit(S->getRangeStmt());
- Visit(S->getBeginEndStmt());
- // Counter tracks the body of the loop.
- RegionMapper Cnt(this, S);
+
+ Counter ParentCount = getRegion().getCounter();
+ Counter BodyCount = getRegionCounter(S);
+
BreakContinueStack.push_back(BreakContinue());
- // Visit the body region first. (This is basically the same as a while
- // loop; see further comments in VisitWhileStmt.)
- Cnt.beginRegion();
- Visit(S->getBody());
- Cnt.adjustForControlFlow();
+ extendRegion(S->getBody());
+ Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
- Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+
+ Counter LoopCount =
+ addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+ Counter OutCount =
+ addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
Visit(S->getElement());
- // Counter tracks the body of the loop.
- RegionMapper Cnt(this, S);
+
+ Counter ParentCount = getRegion().getCounter();
+ Counter BodyCount = getRegionCounter(S);
+
BreakContinueStack.push_back(BreakContinue());
- Cnt.beginRegion();
- Visit(S->getBody());
+ extendRegion(S->getBody());
+ Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+
+ Counter LoopCount =
+ addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+ Counter OutCount =
+ addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitSwitchStmt(const SwitchStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
Visit(S->getCond());
+
BreakContinueStack.push_back(BreakContinue());
- // Map the '}' for the body to have the same count as the regions after
- // the switch.
- SourceLocation RBracLoc;
- if (const auto *CS = dyn_cast<CompoundStmt>(S->getBody())) {
- mapSourceCodeRange(CS->getLBracLoc());
- setCurrentRegionUnreachable(S);
- for (Stmt::const_child_range I = CS->children(); I; ++I) {
- if (*I)
- this->Visit(*I);
+
+ const Stmt *Body = S->getBody();
+ extendRegion(Body);
+ if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
+ if (!CS->body_empty()) {
+ // The body of the switch needs a zero region so that fallthrough counts
+ // behave correctly, but it would be misleading to include the braces of
+ // the compound statement in the zeroed area, so we need to handle this
+ // specially.
+ size_t Index =
+ pushRegion(Counter::getZero(), getStart(CS->body_front()),
+ getEnd(CS->body_back()));
+ for (const auto *Child : CS->children())
+ Visit(Child);
+ popRegions(Index);
}
- RBracLoc = CS->getRBracLoc();
- } else {
- setCurrentRegionUnreachable(S);
- Visit(S->getBody());
- }
- // If the switch is inside a loop, add the continue counts.
+ } else
+ propagateCounts(Counter::getZero(), Body);
BreakContinue BC = BreakContinueStack.pop_back_val();
+
if (!BreakContinueStack.empty())
BreakContinueStack.back().ContinueCount = addCounters(
BreakContinueStack.back().ContinueCount, BC.ContinueCount);
- // Counter tracks the exit block of the switch.
- RegionMapper ExitCnt(this, S);
- ExitCnt.beginRegion();
- if (RBracLoc.isValid())
- mapSourceCodeRange(RBracLoc);
- }
- void VisitCaseStmt(const CaseStmt *S) {
- // Counter for this particular case. This counts only jumps from the
- // switch header and does not include fallthrough from the case before
- // this one.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- mapSourceCodeRange(S->getLocStart());
- mapToken(S->getColonLoc());
- Visit(S->getSubStmt());
+ Counter ExitCount = getRegionCounter(S);
+ pushRegion(ExitCount);
}
- void VisitDefaultStmt(const DefaultStmt *S) {
- // Counter for this default case. This does not include fallthrough from
- // the previous case.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
- mapSourceCodeRange(S->getLocStart());
- mapToken(S->getColonLoc());
+ void VisitSwitchCase(const SwitchCase *S) {
+ extendRegion(S);
+
+ SourceMappingRegion &Parent = getRegion();
+
+ Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
+ // Reuse the existing region if it starts at our label. This is typical of
+ // the first case in a switch.
+ if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S))
+ Parent.setCounter(Count);
+ else
+ pushRegion(Count, getStart(S));
+
+ if (const CaseStmt *CS = dyn_cast<CaseStmt>(S)) {
+ Visit(CS->getLHS());
+ if (const Expr *RHS = CS->getRHS())
+ Visit(RHS);
+ }
Visit(S->getSubStmt());
}
void VisitIfStmt(const IfStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- Visit(S->getCond());
- mapToken(S->getElseLoc());
-
- // Counter tracks the "then" part of an if statement. The count for
- // the "else" part, if it exists, will be calculated from this counter.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion();
- Visit(S->getThen());
- Cnt.adjustForControlFlow();
-
- if (S->getElse()) {
- Cnt.beginElseRegion();
- Visit(S->getElse());
- Cnt.adjustForControlFlow();
- }
- Cnt.applyAdjustmentsToRegion();
+ extendRegion(S);
+ // Extend into the condition before we propagate through it below - this is
+ // needed to handle macros that generate the "if" but not the condition.
+ extendRegion(S->getCond());
+
+ Counter ParentCount = getRegion().getCounter();
+ Counter ThenCount = getRegionCounter(S);
+
+ // Emitting a counter for the condition makes it easier to interpret the
+ // counter for the body when looking at the coverage.
+ propagateCounts(ParentCount, S->getCond());
+
+ extendRegion(S->getThen());
+ Counter OutCount = propagateCounts(ThenCount, S->getThen());
+
+ Counter ElseCount = subtractCounters(ParentCount, ThenCount);
+ if (const Stmt *Else = S->getElse()) {
+ extendRegion(S->getElse());
+ OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
+ } else
+ OutCount = addCounters(OutCount, ElseCount);
+
+ if (OutCount != ParentCount)
+ pushRegion(OutCount);
}
void VisitCXXTryStmt(const CXXTryStmt *S) {
- mapSourceCodeRange(S->getLocStart());
+ extendRegion(S);
Visit(S->getTryBlock());
for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
Visit(S->getHandler(I));
- // Counter tracks the continuation block of the try statement.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion();
+
+ Counter ExitCount = getRegionCounter(S);
+ pushRegion(ExitCount);
}
void VisitCXXCatchStmt(const CXXCatchStmt *S) {
- mapSourceCodeRange(S->getLocStart());
- // Counter tracks the catch statement's handler block.
- RegionMapper Cnt(this, S);
- Cnt.beginRegion();
- Visit(S->getHandlerBlock());
+ extendRegion(S);
+ propagateCounts(getRegionCounter(S), S->getHandlerBlock());
}
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
- Visit(E->getCond());
- mapToken(E->getQuestionLoc());
- mapToken(E->getColonLoc());
+ extendRegion(E);
- // Counter tracks the "true" part of a conditional operator. The
- // count in the "false" part will be calculated from this counter.
- RegionMapper Cnt(this, E);
- Cnt.beginRegion();
- Visit(E->getTrueExpr());
- Cnt.adjustForControlFlow();
+ Counter ParentCount = getRegion().getCounter();
+ Counter TrueCount = getRegionCounter(E);
- Cnt.beginElseRegion();
- Visit(E->getFalseExpr());
- Cnt.adjustForControlFlow();
+ Visit(E->getCond());
- Cnt.applyAdjustmentsToRegion();
+ if (!isa<BinaryConditionalOperator>(E)) {
+ extendRegion(E->getTrueExpr());
+ propagateCounts(TrueCount, E->getTrueExpr());
+ }
+ extendRegion(E->getFalseExpr());
+ propagateCounts(subtractCounters(ParentCount, TrueCount),
+ E->getFalseExpr());
}
void VisitBinLAnd(const BinaryOperator *E) {
+ extendRegion(E);
Visit(E->getLHS());
- mapToken(E->getOperatorLoc());
- // Counter tracks the right hand side of a logical and operator.
- RegionMapper Cnt(this, E);
- Cnt.beginRegion();
- Visit(E->getRHS());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion();
- }
-
- void VisitBinLOr(const BinaryOperator *E) {
- Visit(E->getLHS());
- mapToken(E->getOperatorLoc());
- // Counter tracks the right hand side of a logical or operator.
- RegionMapper Cnt(this, E);
- Cnt.beginRegion();
- Visit(E->getRHS());
- Cnt.adjustForControlFlow();
- Cnt.applyAdjustmentsToRegion();
- }
- void VisitParenExpr(const ParenExpr *E) {
- mapToken(E->getLParen());
- Visit(E->getSubExpr());
- mapToken(E->getRParen());
+ extendRegion(E->getRHS());
+ propagateCounts(getRegionCounter(E), E->getRHS());
}
- void VisitBinaryOperator(const BinaryOperator *E) {
- Visit(E->getLHS());
- mapToken(E->getOperatorLoc());
- Visit(E->getRHS());
- }
-
- void VisitUnaryOperator(const UnaryOperator *E) {
- bool Postfix = E->isPostfix();
- if (!Postfix)
- mapToken(E->getOperatorLoc());
- Visit(E->getSubExpr());
- if (Postfix)
- mapToken(E->getOperatorLoc());
- }
-
- void VisitMemberExpr(const MemberExpr *E) {
- Visit(E->getBase());
- mapToken(E->getMemberLoc());
- }
-
- void VisitCallExpr(const CallExpr *E) {
- Visit(E->getCallee());
- for (const auto &Arg : E->arguments())
- Visit(Arg);
- mapToken(E->getRParenLoc());
- }
-
- void VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
+ void VisitBinLOr(const BinaryOperator *E) {
+ extendRegion(E);
Visit(E->getLHS());
- Visit(E->getRHS());
- mapToken(E->getRBracketLoc());
- }
-
- void VisitCStyleCastExpr(const CStyleCastExpr *E) {
- mapToken(E->getLParenLoc());
- mapToken(E->getRParenLoc());
- Visit(E->getSubExpr());
- }
-
- // Map literals as tokens so that the macros like #define PI 3.14
- // won't generate coverage mapping regions.
-
- void VisitIntegerLiteral(const IntegerLiteral *E) {
- mapToken(E->getLocStart());
- }
-
- void VisitFloatingLiteral(const FloatingLiteral *E) {
- mapToken(E->getLocStart());
- }
- void VisitCharacterLiteral(const CharacterLiteral *E) {
- mapToken(E->getLocStart());
+ extendRegion(E->getRHS());
+ propagateCounts(getRegionCounter(E), E->getRHS());
}
- void VisitStringLiteral(const StringLiteral *E) {
- mapToken(E->getLocStart());
- }
-
- void VisitImaginaryLiteral(const ImaginaryLiteral *E) {
- mapToken(E->getLocStart());
- }
-
- void VisitObjCMessageExpr(const ObjCMessageExpr *E) {
- mapToken(E->getLeftLoc());
- for (Stmt::const_child_range I = static_cast<const Stmt*>(E)->children(); I;
- ++I) {
- if (*I)
- this->Visit(*I);
- }
- mapToken(E->getRightLoc());
+ void VisitLambdaExpr(const LambdaExpr *LE) {
+ // Lambdas are treated as their own functions for now, so we shouldn't
+ // propagate counts into them.
}
};
}
@@ -1009,10 +894,12 @@ static StringRef getCoverageSection(const CodeGenModule &CGM) {
return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
}
-static void dump(llvm::raw_ostream &OS, const CoverageMappingRecord &Function) {
- OS << Function.FunctionName << ":\n";
- CounterMappingContext Ctx(Function.Expressions);
- for (const auto &R : Function.MappingRegions) {
+static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
+ ArrayRef<CounterExpression> Expressions,
+ ArrayRef<CounterMappingRegion> Regions) {
+ OS << FunctionName << ":\n";
+ CounterMappingContext Ctx(Expressions);
+ for (const auto &R : Regions) {
OS.indent(2);
switch (R.Kind) {
case CounterMappingRegion::CodeRegion:
@@ -1025,15 +912,12 @@ static void dump(llvm::raw_ostream &OS, const CoverageMappingRecord &Function) {
break;
}
- OS << "File " << R.FileID << ", " << R.LineStart << ":"
- << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd
- << " = ";
- Ctx.dump(R.Count);
- OS << " (HasCodeBefore = " << R.HasCodeBefore;
+ OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
+ << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
+ Ctx.dump(R.Count, OS);
if (R.Kind == CounterMappingRegion::ExpansionRegion)
- OS << ", Expanded file = " << R.ExpandedFileID;
-
- OS << ")\n";
+ OS << " (Expanded file = " << R.ExpandedFileID << ")";
+ OS << "\n";
}
}
@@ -1047,7 +931,8 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
if (!FunctionRecordTy) {
llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty, Int64Ty};
FunctionRecordTy =
- llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes));
+ llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
+ /*isPacked=*/true);
}
llvm::Constant *FunctionRecordVals[] = {
@@ -1072,13 +957,11 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
FilenameRefs.resize(FileEntries.size());
for (const auto &Entry : FileEntries)
FilenameRefs[Entry.second] = Entry.first->getName();
- RawCoverageMappingReader Reader(FunctionNameValue, CoverageMapping,
- FilenameRefs,
- Filenames, Expressions, Regions);
- CoverageMappingRecord FunctionRecord;
- if (Reader.read(FunctionRecord))
+ RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
+ Expressions, Regions);
+ if (Reader.read())
return;
- dump(llvm::outs(), FunctionRecord);
+ dump(llvm::outs(), FunctionNameValue, Expressions, Regions);
}
}
@@ -1098,7 +981,7 @@ void CoverageMappingModuleGen::emit() {
llvm::sys::fs::make_absolute(Path);
auto I = Entry.second;
- FilenameStrs[I] = std::move(std::string(Path.begin(), Path.end()));
+ FilenameStrs[I] = std::string(Path.begin(), Path.end());
FilenameRefs[I] = FilenameStrs[I];
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h b/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
index e695848..a795188 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
@@ -75,8 +76,14 @@ template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
enum CleanupKind : unsigned {
+ /// Denotes a cleanup that should run when a scope is exited using exceptional
+ /// control flow (a throw statement leading to stack unwinding, ).
EHCleanup = 0x1,
+
+ /// Denotes a cleanup that should run when a scope is exited using normal
+ /// control flow (falling off the end of the scope, return, goto, ...).
NormalCleanup = 0x2,
+
NormalAndEHCleanup = EHCleanup | NormalCleanup,
InactiveCleanup = 0x4,
@@ -175,84 +182,28 @@ public:
virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
};
- /// ConditionalCleanupN stores the saved form of its N parameters,
+ /// ConditionalCleanup stores the saved form of its parameters,
/// then restores them and performs the cleanup.
- template <class T, class A0>
- class ConditionalCleanup1 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- A0_saved a0_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- T(a0).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup1(A0_saved a0)
- : a0_saved(a0) {}
- };
-
- template <class T, class A0, class A1>
- class ConditionalCleanup2 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- T(a0, a1).Emit(CGF, flags);
+ template <class T, class... As> class ConditionalCleanup : public Cleanup {
+ typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple;
+ SavedTuple Saved;
+
+ template <std::size_t... Is>
+ T restore(CodeGenFunction &CGF, llvm::index_sequence<Is...>) {
+ // It's important that the restores are emitted in order. The braced init
+ // list guarentees that.
+ return T{DominatingValue<As>::restore(CGF, std::get<Is>(Saved))...};
}
- public:
- ConditionalCleanup2(A0_saved a0, A1_saved a1)
- : a0_saved(a0), a1_saved(a1) {}
- };
-
- template <class T, class A0, class A1, class A2>
- class ConditionalCleanup3 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- typedef typename DominatingValue<A2>::saved_type A2_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
- A2_saved a2_saved;
-
void Emit(CodeGenFunction &CGF, Flags flags) override {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
- T(a0, a1, a2).Emit(CGF, flags);
+ restore(CGF, llvm::index_sequence_for<As...>()).Emit(CGF, flags);
}
public:
- ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
- : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
- };
-
- template <class T, class A0, class A1, class A2, class A3>
- class ConditionalCleanup4 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- typedef typename DominatingValue<A2>::saved_type A2_saved;
- typedef typename DominatingValue<A3>::saved_type A3_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
- A2_saved a2_saved;
- A3_saved a3_saved;
+ ConditionalCleanup(typename DominatingValue<As>::saved_type... A)
+ : Saved(A...) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
- A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
- T(a0, a1, a2, a3).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
- : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
+ ConditionalCleanup(SavedTuple Tuple) : Saved(std::move(Tuple)) {}
};
private:
@@ -306,53 +257,18 @@ public:
InnermostEHScope(stable_end()) {}
~EHScopeStack() { delete[] StartOfBuffer; }
- // Variadic templates would make this not terrible.
-
/// Push a lazily-created cleanup on the stack.
- template <class T>
- void pushCleanup(CleanupKind Kind) {
+ template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T();
+ Cleanup *Obj = new (Buffer) T(A...);
(void) Obj;
}
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0>
- void pushCleanup(CleanupKind Kind, A0 a0) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
+ /// Push a lazily-created cleanup on the stack. Tuple version.
+ template <class T, class... As>
+ void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2, class A3>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2, class A3, class A4>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
+ Cleanup *Obj = new (Buffer) T(std::move(A));
(void) Obj;
}
@@ -369,10 +285,10 @@ public:
///
/// The pointer returned from this method is valid until the cleanup
/// stack is modified.
- template <class T, class A0, class A1, class A2>
- T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
+ template <class T, class... As>
+ T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
- return new (Buffer) T(N, a0, a1, a2);
+ return new (Buffer) T(N, A...);
}
void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) {
@@ -403,6 +319,10 @@ public:
/// Pops a terminate handler off the stack.
void popTerminate();
+ // Returns true iff the current scope is either empty or contains only
+ // lifetime markers, i.e. no real cleanup code
+ bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
+
/// Determines whether the exception-scopes stack is empty.
bool empty() const { return StartOfData == EndOfBuffer; }
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 9e88b1e..70af69b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -19,14 +19,18 @@
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGRecordLayout.h"
#include "CGVTables.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "TargetInfo.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/Type.h"
+#include "clang/AST/StmtCXX.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Value.h"
@@ -90,7 +94,7 @@ public:
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
- llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD) override;
+ llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset) override;
llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;
@@ -111,10 +115,22 @@ public:
const CXXDestructorDecl *Dtor) override;
void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
+ void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
+
+ void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
+
+ llvm::CallInst *
+ emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn) override;
void EmitFundamentalRTTIDescriptor(QualType Type);
void EmitFundamentalRTTIDescriptors();
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
+ llvm::Constant *
+ getAddrOfCXXCatchHandlerType(QualType Ty,
+ QualType CatchHandlerType) override {
+ return getAddrOfRTTIDescriptor(Ty);
+ }
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
@@ -188,7 +204,8 @@ public:
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) override;
+ llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -202,7 +219,7 @@ public:
bool ReturnAdjustment) override {
// Allow inlining of thunks by emitting them with available_externally
// linkage together with vtables when needed.
- if (ForVTable)
+ if (ForVTable && !Thunk->hasLocalLinkage())
Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
}
@@ -639,7 +656,8 @@ ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
}
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *
+ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
return BuildMemberPointer(MD, CharUnits::Zero());
}
@@ -849,7 +867,7 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
/// The Itanium ABI requires non-zero initialization only for data
/// member pointers, for which '0' is a valid offset.
bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
- return MPT->getPointeeType()->isFunctionType();
+ return MPT->isMemberFunctionPointer();
}
/// The Itanium ABI always places an offset to the complete object
@@ -906,6 +924,59 @@ void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
CGF.EmitRuntimeCallOrInvoke(Fn);
}
+static llvm::Constant *getAllocateExceptionFn(CodeGenModule &CGM) {
+ // void *__cxa_allocate_exception(size_t thrown_size);
+
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
+}
+
+static llvm::Constant *getThrowFn(CodeGenModule &CGM) {
+ // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
+ // void (*dest) (void *));
+
+ llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy };
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
+}
+
+void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
+ QualType ThrowType = E->getSubExpr()->getType();
+ // Now allocate the exception object.
+ llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());
+ uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
+
+ llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(CGM);
+ llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall(
+ AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
+
+ CGF.EmitAnyExprToExn(E->getSubExpr(), ExceptionPtr);
+
+ // Now throw the exception.
+ llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
+ /*ForEH=*/true);
+
+ // The address of the destructor. If the exception type has a
+ // trivial destructor (or isn't a record), we just pass null.
+ llvm::Constant *Dtor = nullptr;
+ if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!Record->hasTrivialDestructor()) {
+ CXXDestructorDecl *DtorD = Record->getDestructor();
+ Dtor = CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete);
+ Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy);
+ }
+ }
+ if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+
+ llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
+ CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
+}
+
static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
// void *__dynamic_cast(const void *sub,
// const abi::__class_type_info *src,
@@ -1259,6 +1330,9 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
// Set the correct linkage.
VTable->setLinkage(Linkage);
+ if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
+ VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
+
// Set the right visibility.
CGM.setGlobalVisibility(VTable, RD);
@@ -1278,6 +1352,8 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
DC->getParent()->isTranslationUnit())
EmitFundamentalRTTIDescriptors();
+
+ CGM.EmitVTableBitSetEntries(VTable, VTLayout);
}
llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
@@ -1314,7 +1390,7 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
BaseSubobject Base, const CXXRecordDecl *VTableClass) {
- llvm::Constant *VTable = getAddrOfVTable(VTableClass, CharUnits());
+ auto *VTable = getAddrOfVTable(VTableClass, CharUnits());
// Find the appropriate vtable within the vtable group.
uint64_t AddressPoint = CGM.getItaniumVTableContext()
@@ -1325,7 +1401,8 @@ llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
};
- return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
+ return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable->getValueType(),
+ VTable, Indices);
}
llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
@@ -1364,11 +1441,16 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) {
+ llvm::Type *Ty,
+ SourceLocation Loc) {
GD = GD.getCanonicalDecl();
Ty = Ty->getPointerTo()->getPointerTo();
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
+ if (CGF.SanOpts.has(SanitizerKind::CFIVCall))
+ CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable,
+ CodeGenFunction::CFITCK_VCall, Loc);
+
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
@@ -1385,7 +1467,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
Dtor, getFromDtorType(DtorType));
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee =
- getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
+ getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
+ CE ? CE->getLocStart() : SourceLocation());
CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
/*ImplicitParam=*/nullptr, QualType(), CE);
@@ -1591,7 +1674,7 @@ llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
CGF.Builder.CreateStore(elementSize, cookie);
// The second element is the element count.
- cookie = CGF.Builder.CreateConstInBoundsGEP1_32(cookie, 1);
+ cookie = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.SizeTy, cookie, 1);
CGF.Builder.CreateStore(numElements, cookie);
// Finally, compute a pointer to the actual data buffer by skipping
@@ -1714,11 +1797,12 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// The ABI says: It is suggested that it be emitted in the same COMDAT group
// as the associated data object
- if (!D.isLocalVarDecl() && var->isWeakForLinker() && CGM.supportsCOMDAT()) {
- llvm::Comdat *C = CGM.getModule().getOrInsertComdat(var->getName());
+ llvm::Comdat *C = var->getComdat();
+ if (!D.isLocalVarDecl() && C) {
guard->setComdat(C);
- var->setComdat(C);
CGF.CurFn->setComdat(C);
+ } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
+ guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
}
CGM.setStaticLocalDeclGuardAddress(&D, guard);
@@ -2528,7 +2612,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
// The vtable address point is 2.
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
- VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
+ VTable =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two);
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
Fields.push_back(VTable);
@@ -2718,9 +2803,13 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
+ llvm::Module &M = CGM.getModule();
llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
- /*Constant=*/true, Linkage, Init, Name);
+ new llvm::GlobalVariable(M, Init->getType(),
+ /*Constant=*/true, Linkage, Init, Name);
+
+ if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
+ GV->setComdat(M.getOrInsertComdat(GV->getName()));
// If there's already an old global variable, replace it with the new one.
if (OldGV) {
@@ -3136,8 +3225,8 @@ static void emitConstructorDestructorAlias(CodeGenModule &CGM,
llvm::PointerType *AliasType = Aliasee->getType();
// Create the alias with no name.
- auto *Alias = llvm::GlobalAlias::create(
- AliasType->getElementType(), 0, Linkage, "", Aliasee, &CGM.getModule());
+ auto *Alias = llvm::GlobalAlias::create(AliasType, Linkage, "", Aliasee,
+ &CGM.getModule());
// Switch any previous uses to the alias.
if (Entry) {
@@ -3204,5 +3293,352 @@ void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
getMangleContext().mangleCXXCtorComdat(CD, Out);
llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
Fn->setComdat(C);
+ } else {
+ CGM.maybeSetTrivialComdat(*MD, *Fn);
+ }
+}
+
+static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {
+ // void *__cxa_begin_catch(void*);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(
+ CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
+}
+
+static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {
+ // void __cxa_end_catch();
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
+}
+
+static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {
+ // void *__cxa_get_exception_ptr(void*);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(
+ CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
+}
+
+namespace {
+ /// A cleanup to call __cxa_end_catch. In many cases, the caught
+ /// exception type lets us state definitively that the thrown exception
+ /// type does not have a destructor. In particular:
+ /// - Catch-alls tell us nothing, so we have to conservatively
+ /// assume that the thrown exception might have a destructor.
+ /// - Catches by reference behave according to their base types.
+ /// - Catches of non-record types will only trigger for exceptions
+ /// of non-record types, which never have destructors.
+ /// - Catches of record types can trigger for arbitrary subclasses
+ /// of the caught type, so we have to assume the actual thrown
+ /// exception type might have a throwing destructor, even if the
+ /// caught type's destructor is trivial or nothrow.
+ struct CallEndCatch : EHScopeStack::Cleanup {
+ CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
+ bool MightThrow;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ if (!MightThrow) {
+ CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
+ return;
+ }
+
+ CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
+ }
+ };
+}
+
+/// Emits a call to __cxa_begin_catch and enters a cleanup to call
+/// __cxa_end_catch.
+///
+/// \param EndMightThrow - true if __cxa_end_catch might throw
+static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
+ llvm::Value *Exn,
+ bool EndMightThrow) {
+ llvm::CallInst *call =
+ CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
+
+ CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
+
+ return call;
+}
+
+/// A "special initializer" callback for initializing a catch
+/// parameter during catch initialization.
+static void InitCatchParam(CodeGenFunction &CGF,
+ const VarDecl &CatchParam,
+ llvm::Value *ParamAddr,
+ SourceLocation Loc) {
+ // Load the exception from where the landing pad saved it.
+ llvm::Value *Exn = CGF.getExceptionFromSlot();
+
+ CanQualType CatchType =
+ CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
+ llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
+
+ // If we're catching by reference, we can just cast the object
+ // pointer to the appropriate pointer.
+ if (isa<ReferenceType>(CatchType)) {
+ QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
+ bool EndCatchMightThrow = CaughtType->isRecordType();
+
+ // __cxa_begin_catch returns the adjusted object pointer.
+ llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
+
+ // We have no way to tell the personality function that we're
+ // catching by reference, so if we're catching a pointer,
+ // __cxa_begin_catch will actually return that pointer by value.
+ if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
+ QualType PointeeType = PT->getPointeeType();
+
+ // When catching by reference, generally we should just ignore
+ // this by-value pointer and use the exception object instead.
+ if (!PointeeType->isRecordType()) {
+
+ // Exn points to the struct _Unwind_Exception header, which
+ // we have to skip past in order to reach the exception data.
+ unsigned HeaderSize =
+ CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
+ AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);
+
+ // However, if we're catching a pointer-to-record type that won't
+ // work, because the personality function might have adjusted
+ // the pointer. There's actually no way for us to fully satisfy
+ // the language/ABI contract here: we can't use Exn because it
+ // might have the wrong adjustment, but we can't use the by-value
+ // pointer because it's off by a level of abstraction.
+ //
+ // The current solution is to dump the adjusted pointer into an
+ // alloca, which breaks language semantics (because changing the
+ // pointer doesn't change the exception) but at least works.
+ // The better solution would be to filter out non-exact matches
+ // and rethrow them, but this is tricky because the rethrow
+ // really needs to be catchable by other sites at this landing
+ // pad. The best solution is to fix the personality function.
+ } else {
+ // Pull the pointer for the reference type off.
+ llvm::Type *PtrTy =
+ cast<llvm::PointerType>(LLVMCatchTy)->getElementType();
+
+ // Create the temporary and write the adjusted pointer into it.
+ llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
+ llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+ CGF.Builder.CreateStore(Casted, ExnPtrTmp);
+
+ // Bind the reference to the temporary.
+ AdjustedExn = ExnPtrTmp;
+ }
+ }
+
+ llvm::Value *ExnCast =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
+ CGF.Builder.CreateStore(ExnCast, ParamAddr);
+ return;
+ }
+
+ // Scalars and complexes.
+ TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);
+ if (TEK != TEK_Aggregate) {
+ llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
+
+ // If the catch type is a pointer type, __cxa_begin_catch returns
+ // the pointer by value.
+ if (CatchType->hasPointerRepresentation()) {
+ llvm::Value *CastExn =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
+
+ switch (CatchType.getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ CastExn = CGF.EmitARCRetainNonBlock(CastExn);
+ // fallthrough
+
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ CGF.Builder.CreateStore(CastExn, ParamAddr);
+ return;
+
+ case Qualifiers::OCL_Weak:
+ CGF.EmitARCInitWeak(ParamAddr, CastExn);
+ return;
+ }
+ llvm_unreachable("bad ownership qualifier!");
+ }
+
+ // Otherwise, it returns a pointer into the exception object.
+
+ llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
+ llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+
+ LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);
+ LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,
+ CGF.getContext().getDeclAlign(&CatchParam));
+ switch (TEK) {
+ case TEK_Complex:
+ CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
+ /*init*/ true);
+ return;
+ case TEK_Scalar: {
+ llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);
+ CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
+ return;
+ }
+ case TEK_Aggregate:
+ llvm_unreachable("evaluation kind filtered out!");
+ }
+ llvm_unreachable("bad evaluation kind");
+ }
+
+ assert(isa<RecordType>(CatchType) && "unexpected catch type!");
+
+ llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
+
+ // Check for a copy expression. If we don't have a copy expression,
+ // that means a trivial copy is okay.
+ const Expr *copyExpr = CatchParam.getInit();
+ if (!copyExpr) {
+ llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
+ llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+ CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);
+ return;
+ }
+
+ // We have to call __cxa_get_exception_ptr to get the adjusted
+ // pointer before copying.
+ llvm::CallInst *rawAdjustedExn =
+ CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
+
+ // Cast that to the appropriate type.
+ llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+
+ // The copy expression is defined in terms of an OpaqueValueExpr.
+ // Find it and map it to the adjusted expression.
+ CodeGenFunction::OpaqueValueMapping
+ opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+ CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
+
+ // Call the copy ctor in a terminate scope.
+ CGF.EHStack.pushTerminate();
+
+ // Perform the copy construction.
+ CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);
+ CGF.EmitAggExpr(copyExpr,
+ AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),
+ AggValueSlot::IsNotDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased));
+
+ // Leave the terminate scope.
+ CGF.EHStack.popTerminate();
+
+ // Undo the opaque value mapping.
+ opaque.pop();
+
+ // Finally we can call __cxa_begin_catch.
+ CallBeginCatch(CGF, Exn, true);
+}
+
+/// Begins a catch statement by initializing the catch variable and
+/// calling __cxa_begin_catch.
+void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
+ const CXXCatchStmt *S) {
+ // We have to be very careful with the ordering of cleanups here:
+ // C++ [except.throw]p4:
+ // The destruction [of the exception temporary] occurs
+ // immediately after the destruction of the object declared in
+ // the exception-declaration in the handler.
+ //
+ // So the precise ordering is:
+ // 1. Construct catch variable.
+ // 2. __cxa_begin_catch
+ // 3. Enter __cxa_end_catch cleanup
+ // 4. Enter dtor cleanup
+ //
+ // We do this by using a slightly abnormal initialization process.
+ // Delegation sequence:
+ // - ExitCXXTryStmt opens a RunCleanupsScope
+ // - EmitAutoVarAlloca creates the variable and debug info
+ // - InitCatchParam initializes the variable from the exception
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitAutoVarCleanups enters the variable destructor cleanup
+ // - EmitCXXTryStmt emits the code for the catch body
+ // - EmitCXXTryStmt close the RunCleanupsScope
+
+ VarDecl *CatchParam = S->getExceptionDecl();
+ if (!CatchParam) {
+ llvm::Value *Exn = CGF.getExceptionFromSlot();
+ CallBeginCatch(CGF, Exn, true);
+ return;
+ }
+
+ // Emit the local.
+ CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());
+ CGF.EmitAutoVarCleanups(var);
+}
+
+/// Get or define the following function:
+/// void @__clang_call_terminate(i8* %exn) nounwind noreturn
+/// This code is used only in C++.
+static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
+ llvm::FunctionType *fnTy =
+ llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
+ llvm::Constant *fnRef =
+ CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");
+
+ llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);
+ if (fn && fn->empty()) {
+ fn->setDoesNotThrow();
+ fn->setDoesNotReturn();
+
+ // What we really want is to massively penalize inlining without
+ // forbidding it completely. The difference between that and
+ // 'noinline' is negligible.
+ fn->addFnAttr(llvm::Attribute::NoInline);
+
+ // Allow this function to be shared across translation units, but
+ // we don't want it to turn into an exported symbol.
+ fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
+ fn->setVisibility(llvm::Function::HiddenVisibility);
+ if (CGM.supportsCOMDAT())
+ fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));
+
+ // Set up the function.
+ llvm::BasicBlock *entry =
+ llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
+ CGBuilderTy builder(entry);
+
+ // Pull the exception pointer out of the parameter list.
+ llvm::Value *exn = &*fn->arg_begin();
+
+ // Call __cxa_begin_catch(exn).
+ llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
+ catchCall->setDoesNotThrow();
+ catchCall->setCallingConv(CGM.getRuntimeCC());
+
+ // Call std::terminate().
+ llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
+ termCall->setDoesNotThrow();
+ termCall->setDoesNotReturn();
+ termCall->setCallingConv(CGM.getRuntimeCC());
+
+ // std::terminate cannot return.
+ builder.CreateUnreachable();
+ }
+
+ return fnRef;
+}
+
+llvm::CallInst *
+ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn) {
+ // In C++, we want to call __cxa_begin_catch() before terminating.
+ if (Exn) {
+ assert(CGF.CGM.getLangOpts().CPlusPlus);
+ return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn);
}
+ return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index c067fab..3433990 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -17,12 +17,16 @@
#include "CGCXXABI.h"
#include "CGVTables.h"
#include "CodeGenModule.h"
+#include "CodeGenTypes.h"
+#include "TargetInfo.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/AST/VTableBuilder.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
@@ -40,7 +44,8 @@ public:
MicrosoftCXXABI(CodeGenModule &CGM)
: CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
ClassHierarchyDescriptorType(nullptr),
- CompleteObjectLocatorType(nullptr) {}
+ CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
+ ThrowInfoType(nullptr), CatchHandlerTypeType(nullptr) {}
bool HasThisReturn(GlobalDecl GD) const override;
bool hasMostDerivedReturn(GlobalDecl GD) const override;
@@ -71,11 +76,16 @@ public:
const CXXDestructorDecl *Dtor) override;
void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
+ void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
+
+ void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
const VPtrInfo *Info);
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
+ llvm::Constant *
+ getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override;
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
@@ -195,6 +205,9 @@ public:
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, llvm::Value *This) override;
+ void emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD,
+ llvm::GlobalVariable *VTable);
+
void emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) override;
@@ -211,8 +224,8 @@ public:
CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This,
- llvm::Type *Ty) override;
+ llvm::Value *This, llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -225,7 +238,7 @@ public:
assert(GD.getDtorType() == Dtor_Deleting &&
"Only deleting destructor thunks are available in this ABI");
CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)),
- CGM.getContext().IntTy);
+ getContext().IntTy);
}
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
@@ -234,6 +247,50 @@ public:
getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
llvm::GlobalVariable::LinkageTypes Linkage);
+ llvm::GlobalVariable *
+ getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
+ const CXXRecordDecl *DstRD) {
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);
+ Out.flush();
+ StringRef MangledName = OutName.str();
+
+ if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName))
+ return VDispMap;
+
+ MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext();
+ unsigned NumEntries = 1 + SrcRD->getNumVBases();
+ SmallVector<llvm::Constant *, 4> Map(NumEntries,
+ llvm::UndefValue::get(CGM.IntTy));
+ Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0);
+ bool AnyDifferent = false;
+ for (const auto &I : SrcRD->vbases()) {
+ const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
+ if (!DstRD->isVirtuallyDerivedFrom(VBase))
+ continue;
+
+ unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase);
+ unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase);
+ Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4);
+ AnyDifferent |= SrcVBIndex != DstVBIndex;
+ }
+ // This map would be useless, don't use it.
+ if (!AnyDifferent)
+ return nullptr;
+
+ llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size());
+ llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map);
+ llvm::GlobalValue::LinkageTypes Linkage =
+ SrcRD->isExternallyVisible() && DstRD->isExternallyVisible()
+ ? llvm::GlobalValue::LinkOnceODRLinkage
+ : llvm::GlobalValue::InternalLinkage;
+ auto *VDispMap = new llvm::GlobalVariable(
+ CGM.getModule(), VDispMapTy, /*Constant=*/true, Linkage,
+ /*Initializer=*/Init, MangledName);
+ return VDispMap;
+ }
+
void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD,
llvm::GlobalVariable *GV) const;
@@ -410,6 +467,9 @@ public:
if (!isImageRelative())
return PtrVal;
+ if (PtrVal->isNullValue())
+ return llvm::Constant::getNullValue(CGM.IntTy);
+
llvm::Constant *ImageBaseAsInt =
llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy);
llvm::Constant *PtrValAsInt =
@@ -467,6 +527,10 @@ private:
return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
}
+ std::pair<llvm::Value *, llvm::Value *>
+ performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy);
+
/// \brief Performs a full virtual base adjustment. Used to dereference
/// pointers to members of virtual bases.
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E,
@@ -479,11 +543,8 @@ private:
llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
bool IsMemberFunction,
const CXXRecordDecl *RD,
- CharUnits NonVirtualBaseAdjustment);
-
- llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD,
- const CXXMethodDecl *MD,
- CharUnits NonVirtualBaseAdjustment);
+ CharUnits NonVirtualBaseAdjustment,
+ unsigned VBTableIndex);
bool MemberPointerConstantIsNull(const MemberPointerType *MPT,
llvm::Constant *MP);
@@ -524,7 +585,7 @@ public:
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset) override;
- llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD) override;
+ llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;
llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;
llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
@@ -542,6 +603,12 @@ public:
llvm::Value *Base, llvm::Value *MemPtr,
const MemberPointerType *MPT) override;
+ llvm::Value *EmitNonNullMemberPointerConversion(
+ const MemberPointerType *SrcTy, const MemberPointerType *DstTy,
+ CastKind CK, CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd, llvm::Value *Src,
+ CGBuilderTy &Builder);
+
llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src) override;
@@ -549,6 +616,11 @@ public:
llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
llvm::Constant *Src) override;
+ llvm::Constant *EmitMemberPointerConversion(
+ const MemberPointerType *SrcTy, const MemberPointerType *DstTy,
+ CastKind CK, CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd, llvm::Constant *Src);
+
llvm::Value *
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
llvm::Value *&This, llvm::Value *MemPtr,
@@ -556,6 +628,94 @@ public:
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
+ llvm::StructType *getCatchHandlerTypeType() {
+ if (!CatchHandlerTypeType) {
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy, // Flags
+ CGM.Int8PtrTy, // TypeDescriptor
+ };
+ CatchHandlerTypeType = llvm::StructType::create(
+ CGM.getLLVMContext(), FieldTypes, "eh.CatchHandlerType");
+ }
+ return CatchHandlerTypeType;
+ }
+
+ llvm::StructType *getCatchableTypeType() {
+ if (CatchableTypeType)
+ return CatchableTypeType;
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy, // Flags
+ getImageRelativeType(CGM.Int8PtrTy), // TypeDescriptor
+ CGM.IntTy, // NonVirtualAdjustment
+ CGM.IntTy, // OffsetToVBPtr
+ CGM.IntTy, // VBTableIndex
+ CGM.IntTy, // Size
+ getImageRelativeType(CGM.Int8PtrTy) // CopyCtor
+ };
+ CatchableTypeType = llvm::StructType::create(
+ CGM.getLLVMContext(), FieldTypes, "eh.CatchableType");
+ return CatchableTypeType;
+ }
+
+ llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
+ llvm::StructType *&CatchableTypeArrayType =
+ CatchableTypeArrayTypeMap[NumEntries];
+ if (CatchableTypeArrayType)
+ return CatchableTypeArrayType;
+
+ llvm::SmallString<23> CTATypeName("eh.CatchableTypeArray.");
+ CTATypeName += llvm::utostr(NumEntries);
+ llvm::Type *CTType =
+ getImageRelativeType(getCatchableTypeType()->getPointerTo());
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy, // NumEntries
+ llvm::ArrayType::get(CTType, NumEntries) // CatchableTypes
+ };
+ CatchableTypeArrayType =
+ llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, CTATypeName);
+ return CatchableTypeArrayType;
+ }
+
+ llvm::StructType *getThrowInfoType() {
+ if (ThrowInfoType)
+ return ThrowInfoType;
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy, // Flags
+ getImageRelativeType(CGM.Int8PtrTy), // CleanupFn
+ getImageRelativeType(CGM.Int8PtrTy), // ForwardCompat
+ getImageRelativeType(CGM.Int8PtrTy) // CatchableTypeArray
+ };
+ ThrowInfoType = llvm::StructType::create(CGM.getLLVMContext(), FieldTypes,
+ "eh.ThrowInfo");
+ return ThrowInfoType;
+ }
+
+ llvm::Constant *getThrowFn() {
+ // _CxxThrowException is passed an exception object and a ThrowInfo object
+ // which describes the exception.
+ llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()};
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false);
+ auto *Fn = cast<llvm::Function>(
+ CGM.CreateRuntimeFunction(FTy, "_CxxThrowException"));
+ // _CxxThrowException is stdcall on 32-bit x86 platforms.
+ if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86)
+ Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
+ return Fn;
+ }
+
+ llvm::Function *getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
+ CXXCtorType CT);
+
+ llvm::Constant *getCatchableType(QualType T,
+ uint32_t NVOffset = 0,
+ int32_t VBPtrOffset = -1,
+ uint32_t VBIndex = 0);
+
+ llvm::GlobalVariable *getCatchableTypeArray(QualType T);
+
+ llvm::GlobalVariable *getThrowInfo(QualType T) override;
+
private:
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
@@ -582,11 +742,20 @@ private:
/// Map from DeclContext to the current guard variable. We assume that the
/// AST is visited in source code order.
llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
+ llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
+ llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
llvm::StructType *BaseClassDescriptorType;
llvm::StructType *ClassHierarchyDescriptorType;
llvm::StructType *CompleteObjectLocatorType;
+
+ llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
+
+ llvm::StructType *CatchableTypeType;
+ llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
+ llvm::StructType *ThrowInfoType;
+ llvm::StructType *CatchHandlerTypeType;
};
}
@@ -667,55 +836,73 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType);
}
-static llvm::Function *getRethrowFn(CodeGenModule &CGM) {
- // _CxxThrowException takes two pointer width arguments: a value and a context
- // object which points to a TypeInfo object.
- llvm::Type *ArgTypes[] = {CGM.Int8PtrTy, CGM.Int8PtrTy};
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false);
- auto *Fn = cast<llvm::Function>(
- CGM.CreateRuntimeFunction(FTy, "_CxxThrowException"));
- // _CxxThrowException is stdcall on 32-bit x86 platforms.
- if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86)
- Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
- return Fn;
-}
-
void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
- llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.Int8PtrTy),
- llvm::ConstantPointerNull::get(CGM.Int8PtrTy)};
- auto *Fn = getRethrowFn(CGM);
+ llvm::Value *Args[] = {
+ llvm::ConstantPointerNull::get(CGM.Int8PtrTy),
+ llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())};
+ auto *Fn = getThrowFn();
if (isNoReturn)
CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, Args);
else
CGF.EmitRuntimeCallOrInvoke(Fn, Args);
}
-/// \brief Gets the offset to the virtual base that contains the vfptr for
-/// MS-ABI polymorphic types.
-static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
- const CXXRecordDecl *RD,
- llvm::Value *Value) {
- const ASTContext &Context = RD->getASTContext();
- for (const CXXBaseSpecifier &Base : RD->vbases())
- if (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
- .hasExtendableVFPtr())
- return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
- CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
- llvm_unreachable("One of our vbases should be polymorphic.");
+namespace {
+struct CallEndCatchMSVC : EHScopeStack::Cleanup {
+ CallEndCatchMSVC() {}
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitNounwindRuntimeCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch));
+ }
+};
+}
+
+void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
+ const CXXCatchStmt *S) {
+ // In the MS ABI, the runtime handles the copy, and the catch handler is
+ // responsible for destruction.
+ VarDecl *CatchParam = S->getExceptionDecl();
+ llvm::Value *Exn = CGF.getExceptionFromSlot();
+ llvm::Function *BeginCatch =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
+
+ // If this is a catch-all or the catch parameter is unnamed, we don't need to
+ // emit an alloca to the object.
+ if (!CatchParam || !CatchParam->getDeclName()) {
+ llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};
+ CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+ CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
+ return;
+ }
+
+ CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ llvm::Value *ParamAddr =
+ CGF.Builder.CreateBitCast(var.getObjectAddress(CGF), CGF.Int8PtrTy);
+ llvm::Value *Args[2] = {Exn, ParamAddr};
+ CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+ CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
+ CGF.EmitAutoVarCleanups(var);
}
-static std::pair<llvm::Value *, llvm::Value *>
-performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
- QualType SrcRecordTy) {
+std::pair<llvm::Value *, llvm::Value *>
+MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy) {
Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+ const ASTContext &Context = getContext();
- if (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
+ if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0));
// Perform a base adjustment.
- llvm::Value *Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
+ const CXXBaseSpecifier *PolymorphicBase = std::find_if(
+ SrcDecl->vbases_begin(), SrcDecl->vbases_end(),
+ [&](const CXXBaseSpecifier &Base) {
+ const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+ return Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr();
+ });
+ llvm::Value *Offset = GetVirtualBaseClassOffset(
+ CGF, Value, SrcDecl, PolymorphicBase->getType()->getAsCXXRecordDecl());
Value = CGF.Builder.CreateInBoundsGEP(Value, Offset);
Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
return std::make_pair(Value, Offset);
@@ -725,7 +912,7 @@ bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
QualType SrcRecordTy) {
const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
return IsDeref &&
- !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
+ !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
}
static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF,
@@ -759,7 +946,7 @@ bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
QualType SrcRecordTy) {
const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
return SrcIsPtr &&
- !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
+ !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
}
llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
@@ -817,10 +1004,11 @@ bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
CodeGenFunction &CGF, llvm::Value *This, const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) {
+ const ASTContext &Context = getContext();
int64_t VBPtrChars =
- getContext().getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity();
+ Context.getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity();
llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
- CharUnits IntSize = getContext().getTypeSizeInChars(getContext().IntTy);
+ CharUnits IntSize = Context.getTypeSizeInChars(Context.IntTy);
CharUnits VBTableChars =
IntSize *
CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl);
@@ -947,30 +1135,52 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
}
}
+static bool hasDefaultCXXMethodCC(ASTContext &Context,
+ const CXXMethodDecl *MD) {
+ CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+ CallingConv ActualCallingConv =
+ MD->getType()->getAs<FunctionProtoType>()->getCallConv();
+ return ExpectedCallingConv == ActualCallingConv;
+}
+
void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
// There's only one constructor type in this ABI.
CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
+
+ // Exported default constructors either have a simple call-site where they use
+ // the typical calling convention and have a single 'this' pointer for an
+ // argument -or- they get a wrapper function which appropriately thunks to the
+ // real default constructor. This thunk is the default constructor closure.
+ if (D->hasAttr<DLLExportAttr>() && D->isDefaultConstructor())
+ if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) {
+ llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure);
+ Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
+ Fn->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ }
}
void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
llvm::Value *ThisInt8Ptr =
CGF.Builder.CreateBitCast(getThisValue(CGF), CGM.Int8PtrTy, "this.int8");
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const ASTContext &Context = getContext();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
const ASTRecordLayout &SubobjectLayout =
- CGM.getContext().getASTRecordLayout(VBT->BaseWithVPtr);
+ Context.getASTRecordLayout(VBT->BaseWithVPtr);
CharUnits Offs = VBT->NonVirtualOffset;
Offs += SubobjectLayout.getVBPtrOffset();
if (VBT->getVBaseWithVPtr())
Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr());
llvm::Value *VBPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs.getQuantity());
- llvm::Value *GVPtr = CGF.Builder.CreateConstInBoundsGEP2_32(GV, 0, 0);
+ llvm::Value *GVPtr =
+ CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0);
VBPtr = CGF.Builder.CreateBitCast(VBPtr, GVPtr->getType()->getPointerTo(0),
"vbptr." + VBT->ReusingBase->getName());
CGF.Builder.CreateStore(GVPtr, VBPtr);
@@ -983,7 +1193,7 @@ MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
// TODO: 'for base' flag
if (T == StructorType::Deleting) {
// The scalar deleting destructor takes an implicit int parameter.
- ArgTys.push_back(CGM.getContext().IntTy);
+ ArgTys.push_back(getContext().IntTy);
}
auto *CD = dyn_cast<CXXConstructorDecl>(MD);
if (!CD)
@@ -996,9 +1206,9 @@ MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>();
if (Class->getNumVBases()) {
if (FPT->isVariadic())
- ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
+ ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
else
- ArgTys.push_back(CGM.getContext().IntTy);
+ ArgTys.push_back(getContext().IntTy);
}
}
@@ -1038,7 +1248,7 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
if (ML.VBase) {
const ASTRecordLayout &DerivedLayout =
- CGM.getContext().getASTRecordLayout(MD->getParent());
+ getContext().getASTRecordLayout(MD->getParent());
Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase);
}
@@ -1104,7 +1314,7 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
// FIXME: Update the code that emits this adjustment in thunks prologues.
This = CGF.Builder.CreateConstGEP1_32(This, StaticOffset.getQuantity());
} else {
- This = CGF.Builder.CreateConstInBoundsGEP1_32(This,
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
StaticOffset.getQuantity());
}
}
@@ -1159,8 +1369,8 @@ llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue(
This = CGF.Builder.CreateBitCast(This, charPtrTy);
assert(Adjustment.isPositive());
- This =
- CGF.Builder.CreateConstInBoundsGEP1_32(This, -Adjustment.getQuantity());
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
+ -Adjustment.getQuantity());
return CGF.Builder.CreateBitCast(This, thisTy);
}
@@ -1245,6 +1455,66 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
getFromDtorType(Type));
}
+void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
+ const CXXRecordDecl *RD,
+ llvm::GlobalVariable *VTable) {
+ if (!getContext().getLangOpts().Sanitize.has(SanitizerKind::CFIVCall) &&
+ !getContext().getLangOpts().Sanitize.has(SanitizerKind::CFINVCall) &&
+ !getContext().getLangOpts().Sanitize.has(SanitizerKind::CFIDerivedCast) &&
+ !getContext().getLangOpts().Sanitize.has(SanitizerKind::CFIUnrelatedCast))
+ return;
+
+ llvm::NamedMDNode *BitsetsMD =
+ CGM.getModule().getOrInsertNamedMetadata("llvm.bitsets");
+
+ // 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()) {
+ 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.
+ 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.
+ for (unsigned I = Info->PathToBaseWithVPtr.size() - 1; I != 0; --I) {
+ const CXXRecordDecl *DerivedRD = Info->PathToBaseWithVPtr[I - 1];
+ const CXXRecordDecl *BaseRD = Info->PathToBaseWithVPtr[I];
+
+ const ASTRecordLayout &Layout =
+ getContext().getASTRecordLayout(DerivedRD);
+ CharUnits Offset;
+ auto VBI = Layout.getVBaseOffsetsMap().find(BaseRD);
+ if (VBI == Layout.getVBaseOffsetsMap().end())
+ Offset = Layout.getBaseClassOffset(BaseRD);
+ else
+ Offset = VBI->second.VBaseOffset;
+ if (!Offset.isZero())
+ return;
+ if (!CGM.IsCFIBlacklistedRecord(DerivedRD))
+ BitsetsMD->addOperand(
+ CGM.CreateVTableBitSetEntry(VTable, AddressPoint, DerivedRD));
+ }
+
+ // Finally do the same for the most derived class.
+ if (Info->FullOffsetInMDC.isZero() && !CGM.IsCFIBlacklistedRecord(RD))
+ BitsetsMD->addOperand(
+ CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD));
+}
+
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) {
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
@@ -1267,6 +1537,8 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
VTLayout.getNumVTableThunks(), RTTI);
VTable->setInitializer(Init);
+
+ emitVTableBitSetEntries(Info, RD, VTable);
}
}
@@ -1280,7 +1552,7 @@ llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
if (!VTableAddressPoint) {
assert(Base.getBase()->getNumVBases() &&
- !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
+ !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
}
return VTableAddressPoint;
}
@@ -1336,105 +1608,147 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
#endif
}
- for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
- if (VFPtrs[J]->FullOffsetInMDC != VPtrOffset)
- continue;
- SmallString<256> VFTableName;
- mangleVFTableName(getMangleContext(), RD, VFPtrs[J], VFTableName);
- StringRef VTableName = VFTableName;
-
- uint64_t NumVTableSlots =
- VTContext.getVFTableLayout(RD, VFPtrs[J]->FullOffsetInMDC)
- .getNumVTableComponents();
- llvm::GlobalValue::LinkageTypes VTableLinkage =
- llvm::GlobalValue::ExternalLinkage;
- llvm::ArrayType *VTableType =
- llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);
- if (getContext().getLangOpts().RTTIData) {
- VTableLinkage = llvm::GlobalValue::PrivateLinkage;
- VTableName = "";
+ VPtrInfo *const *VFPtrI =
+ std::find_if(VFPtrs.begin(), VFPtrs.end(), [&](VPtrInfo *VPI) {
+ return VPI->FullOffsetInMDC == VPtrOffset;
+ });
+ if (VFPtrI == VFPtrs.end()) {
+ VFTablesMap[ID] = nullptr;
+ return nullptr;
+ }
+ VPtrInfo *VFPtr = *VFPtrI;
+
+ SmallString<256> VFTableName;
+ mangleVFTableName(getMangleContext(), RD, VFPtr, VFTableName);
+
+ llvm::GlobalValue::LinkageTypes VFTableLinkage = CGM.getVTableLinkage(RD);
+ bool VFTableComesFromAnotherTU =
+ llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
+ llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
+ bool VTableAliasIsRequred =
+ !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
+
+ if (llvm::GlobalValue *VFTable =
+ CGM.getModule().getNamedGlobal(VFTableName)) {
+ VFTablesMap[ID] = VFTable;
+ return VTableAliasIsRequred
+ ? cast<llvm::GlobalVariable>(
+ cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
+ : cast<llvm::GlobalVariable>(VFTable);
+ }
+
+ uint64_t NumVTableSlots =
+ VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC)
+ .getNumVTableComponents();
+ llvm::GlobalValue::LinkageTypes VTableLinkage =
+ VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
+
+ StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
+
+ llvm::ArrayType *VTableType =
+ llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);
+
+ // Create a backing variable for the contents of VTable. The VTable may
+ // or may not include space for a pointer to RTTI data.
+ llvm::GlobalValue *VFTable;
+ VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType,
+ /*isConstant=*/true, VTableLinkage,
+ /*Initializer=*/nullptr, VTableName);
+ VTable->setUnnamedAddr(true);
+
+ llvm::Comdat *C = nullptr;
+ if (!VFTableComesFromAnotherTU &&
+ (llvm::GlobalValue::isWeakForLinker(VFTableLinkage) ||
+ (llvm::GlobalValue::isLocalLinkage(VFTableLinkage) &&
+ VTableAliasIsRequred)))
+ C = CGM.getModule().getOrInsertComdat(VFTableName.str());
+
+ // Only insert a pointer into the VFTable for RTTI data if we are not
+ // importing it. We never reference the RTTI data directly so there is no
+ // need to make room for it.
+ if (VTableAliasIsRequred) {
+ llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
+ llvm::ConstantInt::get(CGM.IntTy, 1)};
+ // Create a GEP which points just after the first entry in the VFTable,
+ // this should be the location of the first virtual method.
+ llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
+ VTable->getValueType(), VTable, GEPIndices);
+ if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
+ VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
+ if (C)
+ C->setSelectionKind(llvm::Comdat::Largest);
}
+ VFTable = llvm::GlobalAlias::create(
+ cast<llvm::PointerType>(VTableGEP->getType()), VFTableLinkage,
+ VFTableName.str(), VTableGEP, &CGM.getModule());
+ VFTable->setUnnamedAddr(true);
+ } else {
+ // We don't need a GlobalAlias to be a symbol for the VTable if we won't
+ // be referencing any RTTI data.
+ // The GlobalVariable will end up being an appropriate definition of the
+ // VFTable.
+ VFTable = VTable;
+ }
+ if (C)
+ VTable->setComdat(C);
- VTable = CGM.getModule().getNamedGlobal(VFTableName);
- if (!VTable) {
- // Create a backing variable for the contents of VTable. The VTable may
- // or may not include space for a pointer to RTTI data.
- llvm::GlobalValue *VFTable = VTable = new llvm::GlobalVariable(
- CGM.getModule(), VTableType, /*isConstant=*/true, VTableLinkage,
- /*Initializer=*/nullptr, VTableName);
- VTable->setUnnamedAddr(true);
-
- // Only insert a pointer into the VFTable for RTTI data if we are not
- // importing it. We never reference the RTTI data directly so there is no
- // need to make room for it.
- if (getContext().getLangOpts().RTTIData &&
- !RD->hasAttr<DLLImportAttr>()) {
- llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
- llvm::ConstantInt::get(CGM.IntTy, 1)};
- // Create a GEP which points just after the first entry in the VFTable,
- // this should be the location of the first virtual method.
- llvm::Constant *VTableGEP =
- llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, GEPIndices);
- // The symbol for the VFTable is an alias to the GEP. It is
- // transparent, to other modules, what the nature of this symbol is; all
- // that matters is that the alias be the address of the first virtual
- // method.
- VFTable = llvm::GlobalAlias::create(
- cast<llvm::SequentialType>(VTableGEP->getType())->getElementType(),
- /*AddressSpace=*/0, llvm::GlobalValue::ExternalLinkage,
- VFTableName.str(), VTableGEP, &CGM.getModule());
- } else {
- // We don't need a GlobalAlias to be a symbol for the VTable if we won't
- // be referencing any RTTI data. The GlobalVariable will end up being
- // an appropriate definition of the VFTable.
- VTable->setName(VFTableName.str());
- }
+ if (RD->hasAttr<DLLImportAttr>())
+ VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else if (RD->hasAttr<DLLExportAttr>())
+ VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- VFTable->setUnnamedAddr(true);
- if (RD->hasAttr<DLLImportAttr>())
- VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- else if (RD->hasAttr<DLLExportAttr>())
- VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
-
- llvm::GlobalValue::LinkageTypes VFTableLinkage = CGM.getVTableLinkage(RD);
- if (VFTable != VTable) {
- if (llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage)) {
- // AvailableExternally implies that we grabbed the data from another
- // executable. No need to stick the alias in a Comdat.
- } else if (llvm::GlobalValue::isInternalLinkage(VFTableLinkage) ||
- llvm::GlobalValue::isWeakODRLinkage(VFTableLinkage) ||
- llvm::GlobalValue::isLinkOnceODRLinkage(VFTableLinkage)) {
- // The alias is going to be dropped into a Comdat, no need to make it
- // weak.
- if (!llvm::GlobalValue::isInternalLinkage(VFTableLinkage))
- VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
- llvm::Comdat *C =
- CGM.getModule().getOrInsertComdat(VFTable->getName());
- // We must indicate which VFTable is larger to support linking between
- // translation units which do and do not have RTTI data. The largest
- // VFTable contains the RTTI data; translation units which reference
- // the smaller VFTable always reference it relative to the first
- // virtual method.
- C->setSelectionKind(llvm::Comdat::Largest);
- VTable->setComdat(C);
- } else {
- llvm_unreachable("unexpected linkage for vftable!");
- }
- }
- VFTable->setLinkage(VFTableLinkage);
- CGM.setGlobalVisibility(VFTable, RD);
- VFTablesMap[ID] = VFTable;
+ VFTablesMap[ID] = VFTable;
+ return VTable;
+}
+
+// Compute the identity of the most derived class whose virtual table is located
+// at the given offset into RD.
+static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx,
+ const CXXRecordDecl *RD,
+ CharUnits Offset) {
+ if (Offset.isZero())
+ return RD;
+
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+ const CXXRecordDecl *MaxBase = nullptr;
+ CharUnits MaxBaseOffset;
+ for (auto &&B : RD->bases()) {
+ const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
+ CharUnits BaseOffset = Layout.getBaseClassOffset(Base);
+ if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
+ MaxBase = Base;
+ MaxBaseOffset = BaseOffset;
}
- break;
}
+ for (auto &&B : RD->vbases()) {
+ const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
+ CharUnits BaseOffset = Layout.getVBaseClassOffset(Base);
+ if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
+ MaxBase = Base;
+ MaxBaseOffset = BaseOffset;
+ }
+ }
+ assert(MaxBase);
+ return getClassAtVTableLocation(Ctx, MaxBase, Offset - MaxBaseOffset);
+}
- return VTable;
+// Compute the identity of the most derived class whose virtual table is located
+// at the MethodVFTableLocation ML.
+static const CXXRecordDecl *
+getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD,
+ MicrosoftVTableContext::MethodVFTableLocation &ML) {
+ const CXXRecordDecl *RD = ML.VBase;
+ if (!RD)
+ RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
+
+ return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset);
}
llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
llvm::Value *This,
- llvm::Type *Ty) {
+ llvm::Type *Ty,
+ SourceLocation Loc) {
GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder;
@@ -1445,6 +1759,10 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
+ if (CGF.SanOpts.has(SanitizerKind::CFIVCall))
+ CGF.EmitVTablePtrCheck(getClassAtVTableLocation(getContext(), GD, ML),
+ VTable, CodeGenFunction::CFITCK_VCall, Loc);
+
llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
return Builder.CreateLoad(VFuncPtr);
@@ -1462,9 +1780,10 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, This, Ty);
+ llvm::Value *Callee = getVirtualFunctionPointer(
+ CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation());
- ASTContext &Context = CGF.getContext();
+ ASTContext &Context = getContext();
llvm::Value *ImplicitParam = llvm::ConstantInt::get(
llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
DtorType == Dtor_Deleting);
@@ -1530,6 +1849,8 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
ThunkFn->setLinkage(MD->isExternallyVisible()
? llvm::GlobalValue::LinkOnceODRLinkage
: llvm::GlobalValue::InternalLinkage);
+ if (MD->isExternallyVisible())
+ ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
@@ -1576,7 +1897,8 @@ void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
- emitVBTableDefinition(*VBT, RD, GV);
+ if (GV->isDeclaration())
+ emitVBTableDefinition(*VBT, RD, GV);
}
}
@@ -1603,6 +1925,9 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
else if (RD->hasAttr<DLLExportAttr>())
GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ if (!GV->hasExternalLinkage())
+ emitVBTableDefinition(VBT, RD, GV);
+
return GV;
}
@@ -1615,9 +1940,8 @@ void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
"should only emit vbtables for classes with vbtables");
const ASTRecordLayout &BaseLayout =
- CGM.getContext().getASTRecordLayout(VBT.BaseWithVPtr);
- const ASTRecordLayout &DerivedLayout =
- CGM.getContext().getASTRecordLayout(RD);
+ getContext().getASTRecordLayout(VBT.BaseWithVPtr);
+ const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(),
nullptr);
@@ -1651,9 +1975,6 @@ void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
llvm::ArrayType::get(CGM.IntTy, Offsets.size());
llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);
GV->setInitializer(Init);
-
- // Set the right visibility.
- CGM.setGlobalVisibility(GV, RD);
}
llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
@@ -1709,8 +2030,8 @@ MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
if (RA.Virtual.Microsoft.VBIndex) {
assert(RA.Virtual.Microsoft.VBIndex > 0);
- int32_t IntSize =
- getContext().getTypeSizeInChars(getContext().IntTy).getQuantity();
+ const ASTContext &Context = getContext();
+ int32_t IntSize = Context.getTypeSizeInChars(Context.IntTy).getQuantity();
llvm::Value *VBPtr;
llvm::Value *VBaseOffset =
GetVBaseOffsetFromVBPtr(CGF, V, RA.Virtual.Microsoft.VBPtrOffset,
@@ -1719,7 +2040,7 @@ MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
}
if (RA.NonVirtual)
- V = CGF.Builder.CreateConstInBoundsGEP1_32(V, RA.NonVirtual);
+ V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual);
// Cast back to the original type.
return CGF.Builder.CreateBitCast(V, Ret->getType());
@@ -1835,18 +2156,10 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
llvm::Function *F = CXXThreadLocalInits[I];
// If the GV is already in a comdat group, then we have to join it.
- llvm::Comdat *C = GV->getComdat();
-
- // LinkOnce and Weak linkage are lowered down to a single-member comdat
- // group.
- // Make an explicit group so we can join it.
- if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) {
- C = CGM.getModule().getOrInsertComdat(GV->getName());
- GV->setComdat(C);
+ if (llvm::Comdat *C = GV->getComdat())
AddToXDU(F)->setComdat(C);
- } else {
+ else
NonComdatInits.push_back(F);
- }
}
if (!NonComdatInits.empty()) {
@@ -1868,6 +2181,81 @@ LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
return LValue();
}
+static llvm::GlobalVariable *getInitThreadEpochPtr(CodeGenModule &CGM) {
+ StringRef VarName("_Init_thread_epoch");
+ if (auto *GV = CGM.getModule().getNamedGlobal(VarName))
+ return GV;
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.IntTy,
+ /*Constant=*/false, llvm::GlobalVariable::ExternalLinkage,
+ /*Initializer=*/nullptr, VarName,
+ /*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
+ GV->setAlignment(CGM.getTarget().getIntAlign() / 8);
+ return GV;
+}
+
+static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(
+ FTy, "_Init_thread_header",
+ llvm::AttributeSet::get(CGM.getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind));
+}
+
+static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(
+ FTy, "_Init_thread_footer",
+ llvm::AttributeSet::get(CGM.getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind));
+}
+
+static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(
+ FTy, "_Init_thread_abort",
+ llvm::AttributeSet::get(CGM.getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind));
+}
+
+namespace {
+struct ResetGuardBit : EHScopeStack::Cleanup {
+ llvm::GlobalVariable *Guard;
+ unsigned GuardNum;
+ ResetGuardBit(llvm::GlobalVariable *Guard, unsigned GuardNum)
+ : Guard(Guard), GuardNum(GuardNum) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ // Reset the bit in the mask so that the static variable may be
+ // reinitialized.
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::LoadInst *LI = Builder.CreateLoad(Guard);
+ llvm::ConstantInt *Mask =
+ llvm::ConstantInt::get(CGF.IntTy, ~(1U << GuardNum));
+ Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);
+ }
+};
+
+struct CallInitThreadAbort : EHScopeStack::Cleanup {
+ llvm::GlobalVariable *Guard;
+ CallInitThreadAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ // Calling _Init_thread_abort will reset the guard's state.
+ CGF.EmitNounwindRuntimeCall(getInitThreadAbortFn(CGF.CGM), Guard);
+ }
+};
+}
+
void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *GV,
bool PerformInit) {
@@ -1875,91 +2263,161 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
if (!D.isStaticLocal()) {
assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
// GlobalOpt is allowed to discard the initializer, so use linkonce_odr.
- CGF.CurFn->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
+ llvm::Function *F = CGF.CurFn;
+ F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
+ F->setComdat(CGM.getModule().getOrInsertComdat(F->getName()));
CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
return;
}
- // MSVC always uses an i32 bitfield to guard initialization, which is *not*
- // threadsafe. Since the user may be linking in inline functions compiled by
- // cl.exe, there's no reason to provide a false sense of security by using
- // critical sections here.
+ bool ThreadlocalStatic = D.getTLSKind();
+ bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;
- if (D.getTLSKind())
- CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
+ // Thread-safe static variables which aren't thread-specific have a
+ // per-variable guard.
+ bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
CGBuilderTy &Builder = CGF.Builder;
llvm::IntegerType *GuardTy = CGF.Int32Ty;
llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
// Get the guard variable for this function if we have one already.
- GuardInfo *GI = &GuardVariableMap[D.getDeclContext()];
-
- unsigned BitIndex;
- if (D.isStaticLocal() && D.isExternallyVisible()) {
+ GuardInfo *GI = nullptr;
+ if (ThreadlocalStatic)
+ GI = &ThreadLocalGuardVariableMap[D.getDeclContext()];
+ else if (!ThreadsafeStatic)
+ GI = &GuardVariableMap[D.getDeclContext()];
+
+ llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr;
+ unsigned GuardNum;
+ if (D.isExternallyVisible()) {
// Externally visible variables have to be numbered in Sema to properly
// handle unreachable VarDecls.
- BitIndex = getContext().getStaticLocalNumber(&D);
- assert(BitIndex > 0);
- BitIndex--;
+ GuardNum = getContext().getStaticLocalNumber(&D);
+ assert(GuardNum > 0);
+ GuardNum--;
+ } else if (HasPerVariableGuard) {
+ GuardNum = ThreadSafeGuardNumMap[D.getDeclContext()]++;
} else {
// Non-externally visible variables are numbered here in CodeGen.
- BitIndex = GI->BitIndex++;
+ GuardNum = GI->BitIndex++;
}
- if (BitIndex >= 32) {
+ if (!HasPerVariableGuard && GuardNum >= 32) {
if (D.isExternallyVisible())
ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
- BitIndex %= 32;
- GI->Guard = nullptr;
+ GuardNum %= 32;
+ GuardVar = nullptr;
}
- // Lazily create the i32 bitfield for this function.
- if (!GI->Guard) {
+ if (!GuardVar) {
// Mangle the name for the guard.
SmallString<256> GuardName;
{
llvm::raw_svector_ostream Out(GuardName);
- getMangleContext().mangleStaticGuardVariable(&D, Out);
+ if (HasPerVariableGuard)
+ getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,
+ Out);
+ else
+ getMangleContext().mangleStaticGuardVariable(&D, Out);
Out.flush();
}
// Create the guard variable with a zero-initializer. Just absorb linkage,
// visibility and dll storage class from the guarded variable.
- GI->Guard =
- new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
+ GuardVar =
+ new llvm::GlobalVariable(CGM.getModule(), GuardTy, /*isConstant=*/false,
GV->getLinkage(), Zero, GuardName.str());
- GI->Guard->setVisibility(GV->getVisibility());
- GI->Guard->setDLLStorageClass(GV->getDLLStorageClass());
- } else {
- assert(GI->Guard->getLinkage() == GV->getLinkage() &&
- "static local from the same function had different linkage");
+ GuardVar->setVisibility(GV->getVisibility());
+ GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
+ if (GuardVar->isWeakForLinker())
+ GuardVar->setComdat(
+ CGM.getModule().getOrInsertComdat(GuardVar->getName()));
+ if (D.getTLSKind())
+ GuardVar->setThreadLocal(true);
+ if (GI && !HasPerVariableGuard)
+ GI->Guard = GuardVar;
}
- // Pseudo code for the test:
- // if (!(GuardVar & MyGuardBit)) {
- // GuardVar |= MyGuardBit;
- // ... initialize the object ...;
- // }
-
- // Test our bit from the guard variable.
- llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIndex);
- llvm::LoadInst *LI = Builder.CreateLoad(GI->Guard);
- llvm::Value *IsInitialized =
- Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
- llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
- llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
- Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+ assert(GuardVar->getLinkage() == GV->getLinkage() &&
+ "static local from the same function had different linkage");
+
+ if (!HasPerVariableGuard) {
+ // Pseudo code for the test:
+ // if (!(GuardVar & MyGuardBit)) {
+ // GuardVar |= MyGuardBit;
+ // ... initialize the object ...;
+ // }
+
+ // Test our bit from the guard variable.
+ llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << GuardNum);
+ llvm::LoadInst *LI = Builder.CreateLoad(GuardVar);
+ llvm::Value *IsInitialized =
+ Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
+ llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+ Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+
+ // Set our bit in the guard variable and emit the initializer and add a global
+ // destructor if appropriate.
+ CGF.EmitBlock(InitBlock);
+ Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardVar);
+ CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardVar, GuardNum);
+ CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
+ CGF.PopCleanupBlock();
+ Builder.CreateBr(EndBlock);
- // Set our bit in the guard variable and emit the initializer and add a global
- // destructor if appropriate.
- CGF.EmitBlock(InitBlock);
- Builder.CreateStore(Builder.CreateOr(LI, Bit), GI->Guard);
- CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
- Builder.CreateBr(EndBlock);
+ // Continue.
+ CGF.EmitBlock(EndBlock);
+ } else {
+ // Pseudo code for the test:
+ // if (TSS > _Init_thread_epoch) {
+ // _Init_thread_header(&TSS);
+ // if (TSS == -1) {
+ // ... initialize the object ...;
+ // _Init_thread_footer(&TSS);
+ // }
+ // }
+ //
+ // The algorithm is almost identical to what can be found in the appendix
+ // found in N2325.
+
+ unsigned IntAlign = CGM.getTarget().getIntAlign() / 8;
+
+ // This BasicBLock determines whether or not we have any work to do.
+ llvm::LoadInst *FirstGuardLoad =
+ Builder.CreateAlignedLoad(GuardVar, IntAlign);
+ FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
+ llvm::LoadInst *InitThreadEpoch =
+ Builder.CreateLoad(getInitThreadEpochPtr(CGM));
+ llvm::Value *IsUninitialized =
+ Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
+ llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+ Builder.CreateCondBr(IsUninitialized, AttemptInitBlock, EndBlock);
+
+ // This BasicBlock attempts to determine whether or not this thread is
+ // responsible for doing the initialization.
+ CGF.EmitBlock(AttemptInitBlock);
+ CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM), GuardVar);
+ llvm::LoadInst *SecondGuardLoad =
+ Builder.CreateAlignedLoad(GuardVar, IntAlign);
+ SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
+ llvm::Value *ShouldDoInit =
+ Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
+ llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+ Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
+
+ // Ok, we ended up getting selected as the initializing thread.
+ CGF.EmitBlock(InitBlock);
+ CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardVar);
+ CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
+ CGF.PopCleanupBlock();
+ CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM), GuardVar);
+ Builder.CreateBr(EndBlock);
- // Continue.
- CGF.EmitBlock(EndBlock);
+ CGF.EmitBlock(EndBlock);
+ }
}
bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
@@ -2040,8 +2498,8 @@ llvm::Constant *
MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
bool IsMemberFunction,
const CXXRecordDecl *RD,
- CharUnits NonVirtualBaseAdjustment)
-{
+ CharUnits NonVirtualBaseAdjustment,
+ unsigned VBTableIndex) {
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
// Single inheritance class member pointer are represented as scalars instead
@@ -2058,14 +2516,14 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) {
CharUnits Offs = CharUnits::Zero();
- if (RD->getNumVBases())
+ if (VBTableIndex)
Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity()));
}
// The rest of the fields are adjusted by conversions to a more derived class.
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
- fields.push_back(getZeroInt());
+ fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex));
return llvm::ConstantStruct::getAnon(fields);
}
@@ -2074,45 +2532,79 @@ llvm::Constant *
MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset) {
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+ if (RD->getMSInheritanceModel() ==
+ MSInheritanceAttr::Keyword_virtual_inheritance)
+ offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
llvm::Constant *FirstField =
llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
- CharUnits::Zero());
-}
-
-llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
- return BuildMemberPointer(MD->getParent(), MD, CharUnits::Zero());
+ CharUnits::Zero(), /*VBTableIndex=*/0);
}
llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
QualType MPType) {
- const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
+ const MemberPointerType *DstTy = MPType->castAs<MemberPointerType>();
const ValueDecl *MPD = MP.getMemberPointerDecl();
if (!MPD)
- return EmitNullMemberPointer(MPT);
+ return EmitNullMemberPointer(DstTy);
- CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP);
+ ASTContext &Ctx = getContext();
+ ArrayRef<const CXXRecordDecl *> MemberPointerPath = MP.getMemberPointerPath();
- // FIXME PR15713: Support virtual inheritance paths.
+ llvm::Constant *C;
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
+ C = EmitMemberFunctionPointer(MD);
+ } else {
+ CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD));
+ C = EmitMemberDataPointer(DstTy, FieldOffset);
+ }
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
- return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD,
- ThisAdjustment);
+ if (!MemberPointerPath.empty()) {
+ const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
+ const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr();
+ const MemberPointerType *SrcTy =
+ Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy)
+ ->castAs<MemberPointerType>();
+
+ bool DerivedMember = MP.isMemberPointerToDerivedMember();
+ SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath;
+ const CXXRecordDecl *PrevRD = SrcRD;
+ for (const CXXRecordDecl *PathElem : MemberPointerPath) {
+ const CXXRecordDecl *Base = nullptr;
+ const CXXRecordDecl *Derived = nullptr;
+ if (DerivedMember) {
+ Base = PathElem;
+ Derived = PrevRD;
+ } else {
+ Base = PrevRD;
+ Derived = PathElem;
+ }
+ for (const CXXBaseSpecifier &BS : Derived->bases())
+ if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
+ Base->getCanonicalDecl())
+ DerivedToBasePath.push_back(&BS);
+ PrevRD = PathElem;
+ }
+ assert(DerivedToBasePath.size() == MemberPointerPath.size());
- CharUnits FieldOffset =
- getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
- return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
+ CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
+ : CK_BaseToDerivedMemberPointer;
+ C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
+ DerivedToBasePath.end(), C);
+ }
+ return C;
}
llvm::Constant *
-MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
- const CXXMethodDecl *MD,
- CharUnits NonVirtualBaseAdjustment) {
+MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
assert(MD->isInstance() && "Member function must not be static!");
+
MD = MD->getCanonicalDecl();
- RD = RD->getMostRecentDecl();
+ CharUnits NonVirtualBaseAdjustment = CharUnits::Zero();
+ const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl();
CodeGenTypes &Types = CGM.getTypes();
+ unsigned VBTableIndex = 0;
llvm::Constant *FirstField;
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
if (!MD->isVirtual()) {
@@ -2127,33 +2619,26 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
Ty = CGM.PtrDiffTy;
}
FirstField = CGM.GetAddrOfFunction(MD, Ty);
- FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
} else {
+ auto &VTableContext = CGM.getMicrosoftVTableContext();
MicrosoftVTableContext::MethodVFTableLocation ML =
- CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
- if (!CGM.getTypes().isFuncTypeConvertible(
- MD->getType()->castAs<FunctionType>())) {
- CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
- "incomplete return or parameter type");
- FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
- } else if (FPT->getCallConv() == CC_X86FastCall) {
- CGM.ErrorUnsupported(MD, "pointer to fastcall virtual member function");
- FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
- } else if (ML.VBase) {
- CGM.ErrorUnsupported(MD, "pointer to virtual member function overriding "
- "member function in virtual base class");
- FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
- } else {
- llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML);
- FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
- // Include the vfptr adjustment if the method is in a non-primary vftable.
- NonVirtualBaseAdjustment += ML.VFPtrOffset;
- }
+ VTableContext.getMethodVFTableLocation(MD);
+ FirstField = EmitVirtualMemPtrThunk(MD, ML);
+ // Include the vfptr adjustment if the method is in a non-primary vftable.
+ NonVirtualBaseAdjustment += ML.VFPtrOffset;
+ if (ML.VBase)
+ VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4;
}
+ if (VBTableIndex == 0 &&
+ RD->getMSInheritanceModel() ==
+ MSInheritanceAttr::Keyword_virtual_inheritance)
+ NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
+
// The rest of the fields are common with data member pointers.
+ FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD,
- NonVirtualBaseAdjustment);
+ NonVirtualBaseAdjustment, VBTableIndex);
}
/// Member pointers are the same if they're either bitwise identical *or* both
@@ -2409,11 +2894,6 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
return Builder.CreateBitCast(Addr, PType);
}
-static MSInheritanceAttr::Spelling
-getInheritanceFromMemptr(const MemberPointerType *MPT) {
- return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel();
-}
-
llvm::Value *
MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
@@ -2465,12 +2945,37 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB);
CGF.EmitBlock(ConvertBB);
+ llvm::Value *Dst = EmitNonNullMemberPointerConversion(
+ SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src,
+ Builder);
+
+ Builder.CreateBr(ContinueBB);
+
+ // In the continuation, choose between DstNull and Dst.
+ CGF.EmitBlock(ContinueBB);
+ llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted");
+ Phi->addIncoming(DstNull, OriginalBB);
+ Phi->addIncoming(Dst, ConvertBB);
+ return Phi;
+}
+
+llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
+ const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd, llvm::Value *Src,
+ CGBuilderTy &Builder) {
+ const CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl();
+ const CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
+ MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
+ MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel();
+ bool IsFunc = SrcTy->isMemberFunctionPointer();
+ bool IsConstant = isa<llvm::Constant>(Src);
+
// Decompose src.
llvm::Value *FirstField = Src;
- llvm::Value *NonVirtualBaseAdjustment = nullptr;
- llvm::Value *VirtualBaseAdjustmentOffset = nullptr;
- llvm::Value *VBPtrOffset = nullptr;
- MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
+ llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
+ llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
+ llvm::Value *VBPtrOffset = getZeroInt();
if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
// We need to extract values.
unsigned I = 0;
@@ -2483,59 +2988,138 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
}
+ bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
+ const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy;
+ const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl();
+
// For data pointers, we adjust the field offset directly. For functions, we
// have a separate field.
- llvm::Constant *Adj = getMemberPointerAdjustment(E);
- if (Adj) {
- Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
- llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
- bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
- if (!NVAdjustField) // If this field didn't exist in src, it's zero.
- NVAdjustField = getZeroInt();
- if (isDerivedToBase)
- NVAdjustField = Builder.CreateNSWSub(NVAdjustField, Adj, "adj");
- else
- NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, Adj, "adj");
+ llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
+
+ // The virtual inheritance model has a quirk: the virtual base table is always
+ // referenced when dereferencing a member pointer even if the member pointer
+ // is non-virtual. This is accounted for by adjusting the non-virtual offset
+ // to point backwards to the top of the MDC from the first VBase. Undo this
+ // adjustment to normalize the member pointer.
+ llvm::Value *SrcVBIndexEqZero =
+ Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
+ if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
+ if (int64_t SrcOffsetToFirstVBase =
+ getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
+ llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
+ SrcVBIndexEqZero,
+ llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase),
+ getZeroInt());
+ NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
+ }
+ }
+
+ // A non-zero vbindex implies that we are dealing with a source member in a
+ // floating virtual base in addition to some non-virtual offset. If the
+ // vbindex is zero, we are dealing with a source that exists in a non-virtual,
+ // fixed, base. The difference between these two cases is that the vbindex +
+ // nvoffset *always* point to the member regardless of what context they are
+ // evaluated in so long as the vbindex is adjusted. A member inside a fixed
+ // base requires explicit nv adjustment.
+ llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
+ CGM.IntTy,
+ CGM.computeNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd)
+ .getQuantity());
+
+ llvm::Value *NVDisp;
+ if (IsDerivedToBase)
+ NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj");
+ else
+ NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj");
+
+ NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
+
+ // Update the vbindex to an appropriate value in the destination because
+ // SrcRD's vbtable might not be a strict prefix of the one in DstRD.
+ llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;
+ if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) &&
+ MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) {
+ if (llvm::GlobalVariable *VDispMap =
+ getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
+ llvm::Value *VBIndex = Builder.CreateExactUDiv(
+ VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4));
+ if (IsConstant) {
+ llvm::Constant *Mapping = VDispMap->getInitializer();
+ VirtualBaseAdjustmentOffset =
+ Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex));
+ } else {
+ llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
+ VirtualBaseAdjustmentOffset =
+ Builder.CreateLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs));
+ }
+
+ DstVBIndexEqZero =
+ Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
+ }
+ }
+
+ // Set the VBPtrOffset to zero if the vbindex is zero. Otherwise, initialize
+ // it to the offset of the vbptr.
+ if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) {
+ llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get(
+ CGM.IntTy,
+ getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
+ VBPtrOffset =
+ Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
}
- // FIXME PR15713: Support conversions through virtually derived classes.
+ // Likewise, apply a similar adjustment so that dereferencing the member
+ // pointer correctly accounts for the distance between the start of the first
+ // virtual base and the top of the MDC.
+ if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
+ if (int64_t DstOffsetToFirstVBase =
+ getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
+ llvm::Value *DoDstAdjustment = Builder.CreateSelect(
+ DstVBIndexEqZero,
+ llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase),
+ getZeroInt());
+ NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
+ }
+ }
// Recompose dst from the null struct and the adjusted fields from src.
- MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel();
llvm::Value *Dst;
if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) {
Dst = FirstField;
} else {
- Dst = llvm::UndefValue::get(DstNull->getType());
+ Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy));
unsigned Idx = 0;
Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance))
- Dst = Builder.CreateInsertValue(
- Dst, getValueOrZeroInt(NonVirtualBaseAdjustment), Idx++);
+ Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance))
- Dst = Builder.CreateInsertValue(
- Dst, getValueOrZeroInt(VBPtrOffset), Idx++);
+ Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance))
- Dst = Builder.CreateInsertValue(
- Dst, getValueOrZeroInt(VirtualBaseAdjustmentOffset), Idx++);
+ Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
}
- Builder.CreateBr(ContinueBB);
-
- // In the continuation, choose between DstNull and Dst.
- CGF.EmitBlock(ContinueBB);
- llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted");
- Phi->addIncoming(DstNull, OriginalBB);
- Phi->addIncoming(Dst, ConvertBB);
- return Phi;
+ return Dst;
}
llvm::Constant *
MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
llvm::Constant *Src) {
const MemberPointerType *SrcTy =
- E->getSubExpr()->getType()->castAs<MemberPointerType>();
+ E->getSubExpr()->getType()->castAs<MemberPointerType>();
const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
+ CastKind CK = E->getCastKind();
+
+ return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(),
+ E->path_end(), Src);
+}
+
+llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
+ const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) {
+ assert(CK == CK_DerivedToBaseMemberPointer ||
+ CK == CK_BaseToDerivedMemberPointer ||
+ CK == CK_ReinterpretMemberPointer);
// If src is null, emit a new null for dst. We can't return src because dst
// might have a new representation.
if (MemberPointerConstantIsNull(SrcTy, Src))
@@ -2544,61 +3128,14 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
// We don't need to do anything for reinterpret_casts of non-null member
// pointers. We should only get here when the two type representations have
// the same size.
- if (E->getCastKind() == CK_ReinterpretMemberPointer)
+ if (CK == CK_ReinterpretMemberPointer)
return Src;
- MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy);
- MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy);
-
- // Decompose src.
- llvm::Constant *FirstField = Src;
- llvm::Constant *NonVirtualBaseAdjustment = nullptr;
- llvm::Constant *VirtualBaseAdjustmentOffset = nullptr;
- llvm::Constant *VBPtrOffset = nullptr;
- bool IsFunc = SrcTy->isMemberFunctionPointer();
- if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
- // We need to extract values.
- unsigned I = 0;
- FirstField = Src->getAggregateElement(I++);
- if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance))
- NonVirtualBaseAdjustment = Src->getAggregateElement(I++);
- if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance))
- VBPtrOffset = Src->getAggregateElement(I++);
- if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance))
- VirtualBaseAdjustmentOffset = Src->getAggregateElement(I++);
- }
+ CGBuilderTy Builder(CGM.getLLVMContext());
+ auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion(
+ SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
- // For data pointers, we adjust the field offset directly. For functions, we
- // have a separate field.
- llvm::Constant *Adj = getMemberPointerAdjustment(E);
- if (Adj) {
- Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
- llvm::Constant *&NVAdjustField =
- IsFunc ? NonVirtualBaseAdjustment : FirstField;
- bool IsDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
- if (!NVAdjustField) // If this field didn't exist in src, it's zero.
- NVAdjustField = getZeroInt();
- if (IsDerivedToBase)
- NVAdjustField = llvm::ConstantExpr::getNSWSub(NVAdjustField, Adj);
- else
- NVAdjustField = llvm::ConstantExpr::getNSWAdd(NVAdjustField, Adj);
- }
-
- // FIXME PR15713: Support conversions through virtually derived classes.
-
- // Recompose dst from the null struct and the adjusted fields from src.
- if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance))
- return FirstField;
-
- llvm::SmallVector<llvm::Constant *, 4> Fields;
- Fields.push_back(FirstField);
- if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance))
- Fields.push_back(getConstantOrZeroInt(NonVirtualBaseAdjustment));
- if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance))
- Fields.push_back(getConstantOrZeroInt(VBPtrOffset));
- if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance))
- Fields.push_back(getConstantOrZeroInt(VirtualBaseAdjustmentOffset));
- return llvm::ConstantStruct::getAnon(Fields);
+ return Dst;
}
llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
@@ -2867,7 +3404,11 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
auto Type = ABI.getClassHierarchyDescriptorType();
auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
/*Initializer=*/nullptr,
- MangledName.c_str());
+ StringRef(MangledName));
+ if (CHD->isWeakForLinker())
+ CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName()));
+
+ auto *Bases = getBaseClassArray(Classes);
// Initialize the base class ClassHierarchyDescriptor.
llvm::Constant *Fields[] = {
@@ -2875,7 +3416,7 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
llvm::ConstantInt::get(CGM.IntTy, Flags),
llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
- getBaseClassArray(Classes),
+ Bases->getValueType(), Bases,
llvm::ArrayRef<llvm::Value *>(GEPIndices))),
};
CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
@@ -2898,9 +3439,12 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
llvm::Type *PtrType = ABI.getImageRelativeType(
ABI.getBaseClassDescriptorType()->getPointerTo());
auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
- auto *BCA = new llvm::GlobalVariable(
- Module, ArrType,
- /*Constant=*/true, Linkage, /*Initializer=*/nullptr, MangledName.c_str());
+ auto *BCA =
+ new llvm::GlobalVariable(Module, ArrType,
+ /*Constant=*/true, Linkage,
+ /*Initializer=*/nullptr, StringRef(MangledName));
+ if (BCA->isWeakForLinker())
+ BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName()));
// Initialize the BaseClassArray.
SmallVector<llvm::Constant *, 8> BaseClassArrayData;
@@ -2938,9 +3482,11 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
// Forward-declare the base class descriptor.
auto Type = ABI.getBaseClassDescriptorType();
- auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/nullptr,
- MangledName.c_str());
+ auto BCD =
+ new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/nullptr, StringRef(MangledName));
+ if (BCD->isWeakForLinker())
+ BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName()));
// Initialize the BaseClassDescriptor.
llvm::Constant *Fields[] = {
@@ -2984,7 +3530,7 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
// Forward-declare the complete object locator.
llvm::StructType *Type = ABI.getCompleteObjectLocatorType();
auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/nullptr, MangledName.c_str());
+ /*Initializer=*/nullptr, StringRef(MangledName));
// Initialize the CompleteObjectLocator.
llvm::Constant *Fields[] = {
@@ -3000,15 +3546,91 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
if (!ABI.isImageRelative())
FieldsRef = FieldsRef.drop_back();
COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef));
+ if (COL->isWeakForLinker())
+ COL->setComdat(CGM.getModule().getOrInsertComdat(COL->getName()));
return COL;
}
+static QualType decomposeTypeForEH(ASTContext &Context, QualType T,
+ bool &IsConst, bool &IsVolatile) {
+ T = Context.getExceptionObjectType(T);
+
+ // C++14 [except.handle]p3:
+ // A handler is a match for an exception object of type E if [...]
+ // - the handler is of type cv T or const T& where T is a pointer type and
+ // E is a pointer type that can be converted to T by [...]
+ // - a qualification conversion
+ IsConst = false;
+ IsVolatile = false;
+ QualType PointeeType = T->getPointeeType();
+ if (!PointeeType.isNull()) {
+ IsConst = PointeeType.isConstQualified();
+ IsVolatile = PointeeType.isVolatileQualified();
+ }
+
+ // Member pointer types like "const int A::*" are represented by having RTTI
+ // for "int A::*" and separately storing the const qualifier.
+ if (const auto *MPTy = T->getAs<MemberPointerType>())
+ T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(),
+ MPTy->getClass());
+
+ // Pointer types like "const int * const *" are represented by having RTTI
+ // for "const int **" and separately storing the const qualifier.
+ if (T->isPointerType())
+ T = Context.getPointerType(PointeeType.getUnqualifiedType());
+
+ return T;
+}
+
+llvm::Constant *
+MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,
+ QualType CatchHandlerType) {
+ // TypeDescriptors for exceptions never have qualified pointer types,
+ // qualifiers are stored seperately in order to support qualification
+ // conversions.
+ bool IsConst, IsVolatile;
+ Type = decomposeTypeForEH(getContext(), Type, IsConst, IsVolatile);
+
+ bool IsReference = CatchHandlerType->isReferenceType();
+
+ uint32_t Flags = 0;
+ if (IsConst)
+ Flags |= 1;
+ if (IsVolatile)
+ Flags |= 2;
+ if (IsReference)
+ Flags |= 8;
+
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXCatchHandlerType(Type, Flags, Out);
+ }
+
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
+ getAddrOfRTTIDescriptor(Type), // TypeDescriptor
+ };
+ llvm::StructType *CatchHandlerTypeType = getCatchHandlerTypeType();
+ auto *Var = new llvm::GlobalVariable(
+ CGM.getModule(), CatchHandlerTypeType, /*Constant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::ConstantStruct::get(CatchHandlerTypeType, Fields),
+ StringRef(MangledName));
+ Var->setUnnamedAddr(true);
+ Var->setSection("llvm.metadata");
+ return Var;
+}
+
/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
/// llvm::GlobalVariable * because different type descriptors have different
/// types, and need to be abstracted. They are abstracting by casting the
/// address to an Int8PtrTy.
llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
- SmallString<256> MangledName, TypeInfoString;
+ SmallString<256> MangledName;
{
llvm::raw_svector_ostream Out(MangledName);
getMangleContext().mangleCXXRTTI(Type, Out);
@@ -3019,6 +3641,7 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
// Compute the fields for the TypeDescriptor.
+ SmallString<256> TypeInfoString;
{
llvm::raw_svector_ostream Out(TypeInfoString);
getMangleContext().mangleCXXRTTIName(Type, Out);
@@ -3031,13 +3654,14 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)};
llvm::StructType *TypeDescriptorType =
getTypeDescriptorType(TypeInfoString);
- return llvm::ConstantExpr::getBitCast(
- new llvm::GlobalVariable(
- CGM.getModule(), TypeDescriptorType, /*Constant=*/false,
- getLinkageForRTTI(Type),
- llvm::ConstantStruct::get(TypeDescriptorType, Fields),
- MangledName.c_str()),
- CGM.Int8PtrTy);
+ auto *Var = new llvm::GlobalVariable(
+ CGM.getModule(), TypeDescriptorType, /*Constant=*/false,
+ getLinkageForRTTI(Type),
+ llvm::ConstantStruct::get(TypeDescriptorType, Fields),
+ StringRef(MangledName));
+ if (Var->isWeakForLinker())
+ Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName()));
+ return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy);
}
/// \brief Gets or a creates a Microsoft CompleteObjectLocator.
@@ -3051,7 +3675,8 @@ static void emitCXXConstructor(CodeGenModule &CGM,
const CXXConstructorDecl *ctor,
StructorType ctorType) {
// There are no constructor variants, always emit the complete destructor.
- CGM.codegenCXXStructor(ctor, StructorType::Complete);
+ llvm::Function *Fn = CGM.codegenCXXStructor(ctor, StructorType::Complete);
+ CGM.maybeSetTrivialComdat(*ctor, *Fn);
}
static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
@@ -3077,7 +3702,9 @@ static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
if (dtorType == StructorType::Base && !CGM.TryEmitBaseDestructorAsAlias(dtor))
return;
- CGM.codegenCXXStructor(dtor, dtorType);
+ llvm::Function *Fn = CGM.codegenCXXStructor(dtor, dtorType);
+ if (Fn->isWeakForLinker())
+ Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName()));
}
void MicrosoftCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
@@ -3088,3 +3715,402 @@ void MicrosoftCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
}
emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type);
}
+
+llvm::Function *
+MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
+ CXXCtorType CT) {
+ assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure);
+
+ // Calculate the mangled name.
+ SmallString<256> ThunkName;
+ llvm::raw_svector_ostream Out(ThunkName);
+ getMangleContext().mangleCXXCtor(CD, CT, Out);
+ Out.flush();
+
+ // If the thunk has been generated previously, just return it.
+ if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
+ return cast<llvm::Function>(GV);
+
+ // Create the llvm::Function.
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT);
+ llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
+ const CXXRecordDecl *RD = CD->getParent();
+ QualType RecordTy = getContext().getRecordType(RD);
+ llvm::Function *ThunkFn = llvm::Function::Create(
+ ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());
+ ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>(
+ FnInfo.getEffectiveCallingConvention()));
+ if (ThunkFn->isWeakForLinker())
+ ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
+ bool IsCopy = CT == Ctor_CopyingClosure;
+
+ // Start codegen.
+ CodeGenFunction CGF(CGM);
+ CGF.CurGD = GlobalDecl(CD, Ctor_Complete);
+
+ // Build FunctionArgs.
+ FunctionArgList FunctionArgs;
+
+ // A constructor always starts with a 'this' pointer as its first argument.
+ buildThisParam(CGF, FunctionArgs);
+
+ // Following the 'this' pointer is a reference to the source object that we
+ // are copying from.
+ ImplicitParamDecl SrcParam(
+ getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"),
+ getContext().getLValueReferenceType(RecordTy,
+ /*SpelledAsLValue=*/true));
+ if (IsCopy)
+ FunctionArgs.push_back(&SrcParam);
+
+ // Constructors for classes which utilize virtual bases have an additional
+ // parameter which indicates whether or not it is being delegated to by a more
+ // derived constructor.
+ ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(),
+ &getContext().Idents.get("is_most_derived"),
+ getContext().IntTy);
+ // Only add the parameter to the list if thie class has virtual bases.
+ if (RD->getNumVBases() > 0)
+ FunctionArgs.push_back(&IsMostDerived);
+
+ // Start defining the function.
+ CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
+ FunctionArgs, CD->getLocation(), SourceLocation());
+ EmitThisParam(CGF);
+ llvm::Value *This = getThisValue(CGF);
+
+ llvm::Value *SrcVal =
+ IsCopy ? CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src")
+ : nullptr;
+
+ CallArgList Args;
+
+ // Push the this ptr.
+ Args.add(RValue::get(This), CD->getThisType(getContext()));
+
+ // Push the src ptr.
+ if (SrcVal)
+ Args.add(RValue::get(SrcVal), SrcParam.getType());
+
+ // Add the rest of the default arguments.
+ std::vector<Stmt *> ArgVec;
+ for (unsigned I = IsCopy ? 1 : 0, E = CD->getNumParams(); I != E; ++I) {
+ Stmt *DefaultArg = getContext().getDefaultArgExprForConstructor(CD, I);
+ assert(DefaultArg && "sema forgot to instantiate default args");
+ ArgVec.push_back(DefaultArg);
+ }
+
+ CodeGenFunction::RunCleanupsScope Cleanups(CGF);
+
+ const auto *FPT = CD->getType()->castAs<FunctionProtoType>();
+ ConstExprIterator ArgBegin(ArgVec.data()),
+ ArgEnd(ArgVec.data() + ArgVec.size());
+ CGF.EmitCallArgs(Args, FPT, ArgBegin, ArgEnd, CD, IsCopy ? 1 : 0);
+
+ // Insert any ABI-specific implicit constructor arguments.
+ unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/false, Args);
+
+ // Call the destructor with our arguments.
+ llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
+ const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
+ Args, CD, Ctor_Complete, ExtraArgs);
+ CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD);
+
+ Cleanups.ForceCleanup();
+
+ // Emit the ret instruction, remove any temporary instructions created for the
+ // aid of CodeGen.
+ CGF.FinishFunction(SourceLocation());
+
+ return ThunkFn;
+}
+
+llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
+ uint32_t NVOffset,
+ int32_t VBPtrOffset,
+ uint32_t VBIndex) {
+ assert(!T->isReferenceType());
+
+ CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ const CXXConstructorDecl *CD =
+ RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr;
+ CXXCtorType CT = Ctor_Complete;
+ if (CD)
+ if (!hasDefaultCXXMethodCC(getContext(), CD) || CD->getNumParams() != 1)
+ CT = Ctor_CopyingClosure;
+
+ uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,
+ VBPtrOffset, VBIndex, Out);
+ }
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+ return getImageRelativeConstant(GV);
+
+ // The TypeDescriptor is used by the runtime to determine if a catch handler
+ // is appropriate for the exception object.
+ llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));
+
+ // The runtime is responsible for calling the copy constructor if the
+ // exception is caught by value.
+ llvm::Constant *CopyCtor;
+ if (CD) {
+ if (CT == Ctor_CopyingClosure)
+ CopyCtor = getAddrOfCXXCtorClosure(CD, Ctor_CopyingClosure);
+ else
+ CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
+
+ CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy);
+ } else {
+ CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+ }
+ CopyCtor = getImageRelativeConstant(CopyCtor);
+
+ bool IsScalar = !RD;
+ bool HasVirtualBases = false;
+ bool IsStdBadAlloc = false; // std::bad_alloc is special for some reason.
+ QualType PointeeType = T;
+ if (T->isPointerType())
+ PointeeType = T->getPointeeType();
+ if (const CXXRecordDecl *RD = PointeeType->getAsCXXRecordDecl()) {
+ HasVirtualBases = RD->getNumVBases() > 0;
+ if (IdentifierInfo *II = RD->getIdentifier())
+ IsStdBadAlloc = II->isStr("bad_alloc") && RD->isInStdNamespace();
+ }
+
+ // Encode the relevant CatchableType properties into the Flags bitfield.
+ // FIXME: Figure out how bits 2 or 8 can get set.
+ uint32_t Flags = 0;
+ if (IsScalar)
+ Flags |= 1;
+ if (HasVirtualBases)
+ Flags |= 4;
+ if (IsStdBadAlloc)
+ Flags |= 16;
+
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
+ TD, // TypeDescriptor
+ llvm::ConstantInt::get(CGM.IntTy, NVOffset), // NonVirtualAdjustment
+ llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), // OffsetToVBPtr
+ llvm::ConstantInt::get(CGM.IntTy, VBIndex), // VBTableIndex
+ llvm::ConstantInt::get(CGM.IntTy, Size), // Size
+ CopyCtor // CopyCtor
+ };
+ llvm::StructType *CTType = getCatchableTypeType();
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), CTType, /*Constant=*/true, getLinkageForRTTI(T),
+ llvm::ConstantStruct::get(CTType, Fields), StringRef(MangledName));
+ GV->setUnnamedAddr(true);
+ GV->setSection(".xdata");
+ if (GV->isWeakForLinker())
+ GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName()));
+ return getImageRelativeConstant(GV);
+}
+
+llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {
+ assert(!T->isReferenceType());
+
+ // See if we've already generated a CatchableTypeArray for this type before.
+ llvm::GlobalVariable *&CTA = CatchableTypeArrays[T];
+ if (CTA)
+ return CTA;
+
+ // Ensure that we don't have duplicate entries in our CatchableTypeArray by
+ // using a SmallSetVector. Duplicates may arise due to virtual bases
+ // occurring more than once in the hierarchy.
+ llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes;
+
+ // C++14 [except.handle]p3:
+ // A handler is a match for an exception object of type E if [...]
+ // - the handler is of type cv T or cv T& and T is an unambiguous public
+ // base class of E, or
+ // - the handler is of type cv T or const T& where T is a pointer type and
+ // E is a pointer type that can be converted to T by [...]
+ // - a standard pointer conversion (4.10) not involving conversions to
+ // pointers to private or protected or ambiguous classes
+ const CXXRecordDecl *MostDerivedClass = nullptr;
+ bool IsPointer = T->isPointerType();
+ if (IsPointer)
+ MostDerivedClass = T->getPointeeType()->getAsCXXRecordDecl();
+ else
+ MostDerivedClass = T->getAsCXXRecordDecl();
+
+ // Collect all the unambiguous public bases of the MostDerivedClass.
+ if (MostDerivedClass) {
+ const ASTContext &Context = getContext();
+ const ASTRecordLayout &MostDerivedLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+ MicrosoftVTableContext &VTableContext = CGM.getMicrosoftVTableContext();
+ SmallVector<MSRTTIClass, 8> Classes;
+ serializeClassHierarchy(Classes, MostDerivedClass);
+ Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr);
+ detectAmbiguousBases(Classes);
+ for (const MSRTTIClass &Class : Classes) {
+ // Skip any ambiguous or private bases.
+ if (Class.Flags &
+ (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
+ continue;
+ // Write down how to convert from a derived pointer to a base pointer.
+ uint32_t OffsetInVBTable = 0;
+ int32_t VBPtrOffset = -1;
+ if (Class.VirtualRoot) {
+ OffsetInVBTable =
+ VTableContext.getVBTableIndex(MostDerivedClass, Class.VirtualRoot)*4;
+ VBPtrOffset = MostDerivedLayout.getVBPtrOffset().getQuantity();
+ }
+
+ // Turn our record back into a pointer if the exception object is a
+ // pointer.
+ QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0);
+ if (IsPointer)
+ RTTITy = Context.getPointerType(RTTITy);
+ CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase,
+ VBPtrOffset, OffsetInVBTable));
+ }
+ }
+
+ // C++14 [except.handle]p3:
+ // A handler is a match for an exception object of type E if
+ // - The handler is of type cv T or cv T& and E and T are the same type
+ // (ignoring the top-level cv-qualifiers)
+ CatchableTypes.insert(getCatchableType(T));
+
+ // C++14 [except.handle]p3:
+ // A handler is a match for an exception object of type E if
+ // - the handler is of type cv T or const T& where T is a pointer type and
+ // E is a pointer type that can be converted to T by [...]
+ // - a standard pointer conversion (4.10) not involving conversions to
+ // pointers to private or protected or ambiguous classes
+ //
+ // C++14 [conv.ptr]p2:
+ // A prvalue of type "pointer to cv T," where T is an object type, can be
+ // converted to a prvalue of type "pointer to cv void".
+ if (IsPointer && T->getPointeeType()->isObjectType())
+ CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
+
+ // C++14 [except.handle]p3:
+ // A handler is a match for an exception object of type E if [...]
+ // - the handler is of type cv T or const T& where T is a pointer or
+ // pointer to member type and E is std::nullptr_t.
+ //
+ // We cannot possibly list all possible pointer types here, making this
+ // implementation incompatible with the standard. However, MSVC includes an
+ // entry for pointer-to-void in this case. Let's do the same.
+ if (T->isNullPtrType())
+ CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
+
+ uint32_t NumEntries = CatchableTypes.size();
+ llvm::Type *CTType =
+ getImageRelativeType(getCatchableTypeType()->getPointerTo());
+ llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
+ llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, NumEntries), // NumEntries
+ llvm::ConstantArray::get(
+ AT, llvm::makeArrayRef(CatchableTypes.begin(),
+ CatchableTypes.end())) // CatchableTypes
+ };
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out);
+ }
+ CTA = new llvm::GlobalVariable(
+ CGM.getModule(), CTAType, /*Constant=*/true, getLinkageForRTTI(T),
+ llvm::ConstantStruct::get(CTAType, Fields), StringRef(MangledName));
+ CTA->setUnnamedAddr(true);
+ CTA->setSection(".xdata");
+ if (CTA->isWeakForLinker())
+ CTA->setComdat(CGM.getModule().getOrInsertComdat(CTA->getName()));
+ return CTA;
+}
+
+llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) {
+ bool IsConst, IsVolatile;
+ T = decomposeTypeForEH(getContext(), T, IsConst, IsVolatile);
+
+ // The CatchableTypeArray enumerates the various (CV-unqualified) types that
+ // the exception object may be caught as.
+ llvm::GlobalVariable *CTA = getCatchableTypeArray(T);
+ // The first field in a CatchableTypeArray is the number of CatchableTypes.
+ // This is used as a component of the mangled name which means that we need to
+ // know what it is in order to see if we have previously generated the
+ // ThrowInfo.
+ uint32_t NumEntries =
+ cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0U))
+ ->getLimitedValue();
+
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, NumEntries,
+ Out);
+ }
+
+ // Reuse a previously generated ThrowInfo if we have generated an appropriate
+ // one before.
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+ return GV;
+
+ // The RTTI TypeDescriptor uses an unqualified type but catch clauses must
+ // be at least as CV qualified. Encode this requirement into the Flags
+ // bitfield.
+ uint32_t Flags = 0;
+ if (IsConst)
+ Flags |= 1;
+ if (IsVolatile)
+ Flags |= 2;
+
+ // The cleanup-function (a destructor) must be called when the exception
+ // object's lifetime ends.
+ llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ if (CXXDestructorDecl *DtorD = RD->getDestructor())
+ if (!DtorD->isTrivial())
+ CleanupFn = llvm::ConstantExpr::getBitCast(
+ CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete),
+ CGM.Int8PtrTy);
+ // This is unused as far as we can tell, initialize it to null.
+ llvm::Constant *ForwardCompat =
+ getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy));
+ llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(
+ llvm::ConstantExpr::getBitCast(CTA, CGM.Int8PtrTy));
+ llvm::StructType *TIType = getThrowInfoType();
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
+ getImageRelativeConstant(CleanupFn), // CleanupFn
+ ForwardCompat, // ForwardCompat
+ PointerToCatchableTypes // CatchableTypeArray
+ };
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), TIType, /*Constant=*/true, getLinkageForRTTI(T),
+ llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName));
+ GV->setUnnamedAddr(true);
+ GV->setSection(".xdata");
+ if (GV->isWeakForLinker())
+ GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName()));
+ return GV;
+}
+
+void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
+ const Expr *SubExpr = E->getSubExpr();
+ QualType ThrowType = SubExpr->getType();
+ // The exception object lives on the stack and it's address is passed to the
+ // runtime function.
+ llvm::AllocaInst *AI = CGF.CreateMemTemp(ThrowType);
+ CGF.EmitAnyExprToMem(SubExpr, AI, ThrowType.getQualifiers(),
+ /*IsInit=*/true);
+
+ // The so-called ThrowInfo is used to describe how the exception object may be
+ // caught.
+ llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
+
+ // Call into the runtime to throw the exception.
+ llvm::Value *Args[] = {CGF.Builder.CreateBitCast(AI, CGM.Int8PtrTy), TI};
+ CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
index 4f1a82e..def56a9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -32,6 +32,8 @@ namespace {
DiagnosticsEngine &Diags;
std::unique_ptr<const llvm::DataLayout> TD;
ASTContext *Ctx;
+ const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
+ const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions CodeGenOpts; // Intentionally copied in.
unsigned HandlingTopLevelDecls;
@@ -56,14 +58,17 @@ namespace {
SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions;
public:
- CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName,
- const CodeGenOptions &CGO, llvm::LLVMContext& C,
+ CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string &ModuleName,
+ const HeaderSearchOptions &HSO,
+ const PreprocessorOptions &PPO, const CodeGenOptions &CGO,
+ llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr)
- : Diags(diags), Ctx(nullptr), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
- CoverageInfo(CoverageInfo),
- M(new llvm::Module(ModuleName, C)) {}
+ : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO),
+ PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
+ CoverageInfo(CoverageInfo),
+ M(new llvm::Module(ModuleName, C)) {}
- virtual ~CodeGeneratorImpl() {
+ ~CodeGeneratorImpl() override {
// There should normally not be any leftover inline method definitions.
assert(DeferredInlineMethodDefinitions.empty() ||
Diags.hasErrorOccurred());
@@ -95,8 +100,12 @@ namespace {
M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
- TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
- Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD,
+ TD.reset(
+ new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
+ Builder.reset(new CodeGen::CodeGenModule(Context,
+ HeaderSearchOpts,
+ PreprocessorOpts,
+ CodeGenOpts, *M, *TD,
Diags, CoverageInfo));
for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)
@@ -211,11 +220,11 @@ namespace {
Builder->EmitTentativeDefinition(D);
}
- void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) override {
+ void HandleVTable(CXXRecordDecl *RD) override {
if (Diags.hasErrorOccurred())
return;
- Builder->EmitVTable(RD, DefinitionRequired);
+ Builder->EmitVTable(RD);
}
void HandleLinkerOptionPragma(llvm::StringRef Opts) override {
@@ -235,11 +244,11 @@ namespace {
void CodeGenerator::anchor() { }
-CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags,
- const std::string& ModuleName,
- const CodeGenOptions &CGO,
- const TargetOptions &/*TO*/,
- llvm::LLVMContext& C,
- CoverageSourceInfo *CoverageInfo) {
- return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, CoverageInfo);
+CodeGenerator *clang::CreateLLVMCodeGen(
+ DiagnosticsEngine &Diags, const std::string &ModuleName,
+ const HeaderSearchOptions &HeaderSearchOpts,
+ const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO,
+ llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) {
+ return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts,
+ PreprocessorOpts, CGO, C, CoverageInfo);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
new file mode 100644
index 0000000..8f04e06
--- /dev/null
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
index 7c38b28..2a338ba 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -25,7 +25,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
SourceLocation Loc, StringRef Name,
QualType Ty, bool IsDynInit,
bool IsBlacklisted) {
- if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
return;
IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
@@ -56,7 +57,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
const VarDecl &D, bool IsDynInit) {
- if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
return;
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -67,7 +69,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
// For now, just make sure the global is not modified by the ASan
// instrumentation.
- if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h
index d2f0651..166f0e6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h
@@ -31,8 +31,8 @@ namespace CodeGen {
class CodeGenModule;
class SanitizerMetadata {
- SanitizerMetadata(const SanitizerMetadata &) LLVM_DELETED_FUNCTION;
- void operator=(const SanitizerMetadata &) LLVM_DELETED_FUNCTION;
+ SanitizerMetadata(const SanitizerMetadata &) = delete;
+ void operator=(const SanitizerMetadata &) = delete;
CodeGenModule &CGM;
public:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index c05b23a..6226d21 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -37,7 +37,8 @@ static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
unsigned LastIndex) {
// Alternatively, we could emit this as a loop in the source.
for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
- llvm::Value *Cell = Builder.CreateConstInBoundsGEP1_32(Array, I);
+ llvm::Value *Cell =
+ Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);
Builder.CreateStore(Value, Cell);
}
}
@@ -107,6 +108,10 @@ bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
return false;
}
+bool ABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
+ return false;
+}
+
void ABIArgInfo::dump() const {
raw_ostream &OS = llvm::errs();
OS << "(ABIArgInfo Kind=";
@@ -238,7 +243,7 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
/// \return The field declaration for the single non-empty field, if
/// it exists.
static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
- const RecordType *RT = T->getAsStructureType();
+ const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return nullptr;
@@ -339,9 +344,15 @@ static bool canExpandIndirectArgument(QualType Ty, ASTContext &Context) {
//
// FIXME: This needs to be generalized to handle classes as well.
const RecordDecl *RD = RT->getDecl();
- if (!RD->isStruct() || isa<CXXRecordDecl>(RD))
+ if (!RD->isStruct())
return false;
+ // We try to expand CLike CXXRecordDecl.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CXXRD->isCLike())
+ return false;
+ }
+
uint64_t Size = 0;
for (const auto *FD : RD->fields()) {
@@ -399,8 +410,16 @@ llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
}
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
- if (isAggregateTypeForABI(Ty))
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
+ if (isAggregateTypeForABI(Ty)) {
+ // Records with non-trivial destructors/copy-constructors should not be
+ // passed by value.
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
+ return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+
return ABIArgInfo::getIndirect(0);
+ }
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
@@ -630,7 +649,7 @@ public:
static bool isStructReturnInRegABI(
const llvm::Triple &Triple, const CodeGenOptions &Opts);
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
@@ -807,7 +826,8 @@ ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(CCState &State) const {
return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false);
}
-ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State) const {
+ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
+ CCState &State) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -1311,7 +1331,7 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
}
}
-void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -1352,7 +1372,8 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
} else {
// 9 is %eflags, which doesn't get a size on Darwin for some
// reason.
- Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9));
+ Builder.CreateStore(
+ Four8, Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, Address, 9));
// 11-16 are st(0..5). Not sure why we stop at 5.
// These have size 12, which is sizeof(long double) on
@@ -1370,6 +1391,26 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
namespace {
+/// The AVX ABI level for X86 targets.
+enum class X86AVXABILevel {
+ None,
+ AVX,
+ AVX512
+};
+
+/// \p returns the size in bits of the largest (native) vector for \p AVXLevel.
+static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) {
+ switch (AVXLevel) {
+ case X86AVXABILevel::AVX512:
+ return 512;
+ case X86AVXABILevel::AVX:
+ return 256;
+ case X86AVXABILevel::None:
+ return 128;
+ }
+ llvm_unreachable("Unknown AVXLevel");
+}
+
/// X86_64ABIInfo - The X86_64 ABI information.
class X86_64ABIInfo : public ABIInfo {
enum Class {
@@ -1475,14 +1516,14 @@ class X86_64ABIInfo : public ABIInfo {
return !getTarget().getTriple().isOSDarwin();
}
- bool HasAVX;
+ X86AVXABILevel AVXLevel;
// Some ABIs (e.g. X32 ABI and Native Client OS) use 32 bit pointers on
// 64-bit hardware.
bool Has64BitPointers;
public:
- X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, bool hasavx) :
- ABIInfo(CGT), HasAVX(hasavx),
+ X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) :
+ ABIInfo(CGT), AVXLevel(AVXLevel),
Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) {
}
@@ -1503,6 +1544,10 @@ public:
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const override;
+
+ bool has64BitPointers() const {
+ return Has64BitPointers;
+ }
};
/// WinX86_64ABIInfo - The Windows X86_64 ABI information.
@@ -1532,10 +1577,9 @@ public:
};
class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
- bool HasAVX;
public:
- X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
- : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)), HasAVX(HasAVX) {}
+ X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel)
+ : TargetCodeGenInfo(new X86_64ABIInfo(CGT, AVXLevel)) {}
const X86_64ABIInfo &getABIInfo() const {
return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
@@ -1588,24 +1632,43 @@ public:
llvm::Constant *
getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override {
- unsigned Sig = (0xeb << 0) | // jmp rel8
- (0x0a << 8) | // .+0x0c
- ('F' << 16) |
- ('T' << 24);
+ unsigned Sig;
+ if (getABIInfo().has64BitPointers())
+ Sig = (0xeb << 0) | // jmp rel8
+ (0x0a << 8) | // .+0x0c
+ ('F' << 16) |
+ ('T' << 24);
+ else
+ Sig = (0xeb << 0) | // jmp rel8
+ (0x06 << 8) | // .+0x08
+ ('F' << 16) |
+ ('T' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
+};
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return HasAVX ? 32 : 16;
+class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
+public:
+ PS4TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel)
+ : X86_64TargetCodeGenInfo(CGT, AVXLevel) {}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const override {
+ Opt = "\01";
+ Opt += Lib;
}
};
static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
- // If the argument does not end in .lib, automatically add the suffix. This
- // matches the behavior of MSVC.
- std::string ArgStr = Lib;
+ // If the argument does not end in .lib, automatically add the suffix.
+ // If the argument contains a space, enclose it in quotes.
+ // This matches the behavior of MSVC.
+ bool Quote = (Lib.find(" ") != StringRef::npos);
+ std::string ArgStr = Quote ? "\"" : "";
+ ArgStr += Lib;
if (!Lib.endswith_lower(".lib"))
ArgStr += ".lib";
+ ArgStr += Quote ? "\"" : "";
return ArgStr;
}
@@ -1615,6 +1678,9 @@ public:
bool d, bool p, bool w, unsigned RegParms)
: X86_32TargetCodeGenInfo(CGT, d, p, w, RegParms) {}
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override;
+
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
Opt = "/DEFAULTLIB:";
@@ -1628,11 +1694,35 @@ public:
}
};
+static void addStackProbeSizeTargetAttribute(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) {
+ if (isa<FunctionDecl>(D)) {
+ if (CGM.getCodeGenOpts().StackProbeSize != 4096) {
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+
+ Fn->addFnAttr("stack-probe-size",
+ llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
+ }
+ }
+}
+
+void WinX86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const {
+ X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+
+ addStackProbeSizeTargetAttribute(D, GV, CGM);
+}
+
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
- bool HasAVX;
public:
- WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
- : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)), HasAVX(HasAVX) {}
+ WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
+ X86AVXABILevel AVXLevel)
+ : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
return 7;
@@ -1659,12 +1749,15 @@ public:
llvm::SmallString<32> &Opt) const override {
Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
}
-
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return HasAVX ? 32 : 16;
- }
};
+void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const {
+ TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+
+ addStackProbeSizeTargetAttribute(D, GV, CGM);
+}
}
void X86_64ABIInfo::postMerge(unsigned AggregateSize, Class &Lo,
@@ -1843,7 +1936,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// split.
if (OffsetBase && OffsetBase != 64)
Hi = Lo;
- } else if (Size == 128 || (HasAVX && isNamedArg && Size == 256)) {
+ } else if (Size == 128 ||
+ (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
// Arguments of 256-bits are split into four eightbyte chunks. The
// least significant one belongs to class SSE and all the others to class
// SSEUP. The original Lo and Hi design considers that types can't be
@@ -1855,6 +1949,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// Note that per 3.5.7 of AMD64-ABI, 256-bit args are only passed in
// registers if they are "named", i.e. not part of the "..." of a
// variadic function.
+ //
+ // Similarly, per 3.2.3. of the AVX512 draft, 512-bits ("named") args are
+ // split into eight eightbyte chunks, one SSE and seven SSEUP.
Lo = SSE;
Hi = SSEUp;
}
@@ -1976,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;
+ }
}
}
@@ -1997,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;
}
@@ -2065,7 +2166,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty) const {
if (const VectorType *VecTy = Ty->getAs<VectorType>()) {
uint64_t Size = getContext().getTypeSize(VecTy);
- unsigned LargestVector = HasAVX ? 256 : 128;
+ unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
if (Size <= 64 || Size > LargestVector)
return true;
}
@@ -2142,20 +2243,16 @@ llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty) const {
Ty = QualType(InnerTy, 0);
llvm::Type *IRType = CGT.ConvertType(Ty);
+ if(isa<llvm::VectorType>(IRType))
+ return IRType;
- // If the preferred type is a 16-byte vector, prefer to pass it.
- if (llvm::VectorType *VT = dyn_cast<llvm::VectorType>(IRType)){
- llvm::Type *EltTy = VT->getElementType();
- unsigned BitWidth = VT->getBitWidth();
- if ((BitWidth >= 128 && BitWidth <= 256) &&
- (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
- EltTy->isIntegerTy(8) || EltTy->isIntegerTy(16) ||
- EltTy->isIntegerTy(32) || EltTy->isIntegerTy(64) ||
- EltTy->isIntegerTy(128)))
- return VT;
- }
+ // We couldn't find the preferred IR vector type for 'Ty'.
+ uint64_t Size = getContext().getTypeSize(Ty);
+ assert((Size == 128 || Size == 256) && "Invalid type found!");
- return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()), 2);
+ // Return a LLVM IR vector type based on the size of 'Ty'.
+ return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()),
+ Size / 64);
}
/// BitsContainNoUserData - Return true if the specified [start,end) bit range
@@ -2394,13 +2491,16 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi,
// of the second element because it might make us access off the end of the
// struct.
if (HiStart != 8) {
- // There are only two sorts of types the ABI generation code can produce for
- // the low part of a pair that aren't 8 bytes in size: float or i8/i16/i32.
+ // There are usually two sorts of types the ABI generation code can produce
+ // for the low part of a pair that aren't 8 bytes in size: float or
+ // i8/i16/i32. This can also include pointers when they are 32-bit (X32 and
+ // NaCl).
// Promote these to a larger type.
if (Lo->isFloatTy())
Lo = llvm::Type::getDoubleTy(Lo->getContext());
else {
- assert(Lo->isIntegerTy() && "Invalid/unknown lo type");
+ assert((Lo->isIntegerTy() || Lo->isPointerTy())
+ && "Invalid/unknown lo type");
Lo = llvm::Type::getInt64Ty(Lo->getContext());
}
}
@@ -2717,8 +2817,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
QualType Ty,
CodeGenFunction &CGF) {
- llvm::Value *overflow_arg_area_p =
- CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_p");
+ llvm::Value *overflow_arg_area_p = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, 2, "overflow_arg_area_p");
llvm::Value *overflow_arg_area =
CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area");
@@ -2775,7 +2875,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
unsigned neededInt, neededSSE;
Ty = CGF.getContext().getCanonicalType(Ty);
- ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE,
+ ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE,
/*isNamedArg*/false);
// AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
@@ -2798,14 +2898,16 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *gp_offset_p = nullptr, *gp_offset = nullptr;
llvm::Value *fp_offset_p = nullptr, *fp_offset = nullptr;
if (neededInt) {
- gp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "gp_offset_p");
+ gp_offset_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "gp_offset_p");
gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
InRegs = llvm::ConstantInt::get(CGF.Int32Ty, 48 - neededInt * 8);
InRegs = CGF.Builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp");
}
if (neededSSE) {
- fp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 1, "fp_offset_p");
+ fp_offset_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 1, "fp_offset_p");
fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset");
llvm::Value *FitsInFP =
llvm::ConstantInt::get(CGF.Int32Ty, 176 - neededSSE * 16);
@@ -2833,9 +2935,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// simple assembling of a structure from scattered addresses has many more
// loads than necessary. Can we clean this up?
llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *RegAddr =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3),
- "reg_save_area");
+ llvm::Value *RegAddr = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3), "reg_save_area");
if (neededInt && neededSSE) {
// FIXME: Cleanup.
assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
@@ -2855,9 +2956,9 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
llvm::Value *V =
CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
RegAddr = CGF.Builder.CreateBitCast(Tmp,
llvm::PointerType::getUnqual(LTy));
@@ -2894,10 +2995,10 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi,
DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
RegAddr = CGF.Builder.CreateBitCast(Tmp,
llvm::PointerType::getUnqual(LTy));
}
@@ -2984,7 +3085,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
return ABIArgInfo::getDirect();
}
- if (RT || Ty->isMemberPointerType()) {
+ if (RT || Ty->isAnyComplexType() || Ty->isMemberPointerType()) {
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
// not 1, 2, 4, or 8 bytes, must be passed by reference."
if (Width > 64 || !llvm::isPowerOf2_64(Width))
@@ -3040,48 +3141,6 @@ llvm::Value *WinX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return AddrTyped;
}
-namespace {
-
-class NaClX86_64ABIInfo : public ABIInfo {
- public:
- NaClX86_64ABIInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
- : ABIInfo(CGT), PInfo(CGT), NInfo(CGT, HasAVX) {}
- void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
- private:
- PNaClABIInfo PInfo; // Used for generating calls with pnaclcall callingconv.
- X86_64ABIInfo NInfo; // Used for everything else.
-};
-
-class NaClX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
- bool HasAVX;
- public:
- NaClX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
- : TargetCodeGenInfo(new NaClX86_64ABIInfo(CGT, HasAVX)), HasAVX(HasAVX) {
- }
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return HasAVX ? 32 : 16;
- }
-};
-
-}
-
-void NaClX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
- if (FI.getASTCallingConvention() == CC_PnaclCall)
- PInfo.computeInfo(FI);
- else
- NInfo.computeInfo(FI);
-}
-
-llvm::Value *NaClX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // Always use the native convention; calling pnacl-style varargs functions
- // is unuspported.
- return NInfo.EmitVAArg(VAListAddr, Ty, CGF);
-}
-
-
// PowerPC-32
namespace {
/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information.
@@ -3095,7 +3154,8 @@ public:
class PPC32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- PPC32TargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT)) {}
+ PPC32TargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
// This is recovered from gcc output.
@@ -3104,10 +3164,6 @@ public:
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override;
-
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return 16; // Natural alignment for Altivec vectors.
- }
};
}
@@ -3122,19 +3178,25 @@ llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
}
bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64;
- bool isInt = Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType();
+ bool isInt =
+ Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType();
llvm::Type *CharPtr = CGF.Int8PtrTy;
llvm::Type *CharPtrPtr = CGF.Int8PtrPtrTy;
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *GPRPtr = Builder.CreateBitCast(VAListAddr, CharPtr, "gprptr");
llvm::Value *GPRPtrAsInt = Builder.CreatePtrToInt(GPRPtr, CGF.Int32Ty);
- llvm::Value *FPRPtrAsInt = Builder.CreateAdd(GPRPtrAsInt, Builder.getInt32(1));
+ llvm::Value *FPRPtrAsInt =
+ Builder.CreateAdd(GPRPtrAsInt, Builder.getInt32(1));
llvm::Value *FPRPtr = Builder.CreateIntToPtr(FPRPtrAsInt, CharPtr);
- llvm::Value *OverflowAreaPtrAsInt = Builder.CreateAdd(FPRPtrAsInt, Builder.getInt32(3));
- llvm::Value *OverflowAreaPtr = Builder.CreateIntToPtr(OverflowAreaPtrAsInt, CharPtrPtr);
- llvm::Value *RegsaveAreaPtrAsInt = Builder.CreateAdd(OverflowAreaPtrAsInt, Builder.getInt32(4));
- llvm::Value *RegsaveAreaPtr = Builder.CreateIntToPtr(RegsaveAreaPtrAsInt, CharPtrPtr);
+ llvm::Value *OverflowAreaPtrAsInt =
+ Builder.CreateAdd(FPRPtrAsInt, Builder.getInt32(3));
+ llvm::Value *OverflowAreaPtr =
+ Builder.CreateIntToPtr(OverflowAreaPtrAsInt, CharPtrPtr);
+ llvm::Value *RegsaveAreaPtrAsInt =
+ Builder.CreateAdd(OverflowAreaPtrAsInt, Builder.getInt32(4));
+ llvm::Value *RegsaveAreaPtr =
+ Builder.CreateIntToPtr(RegsaveAreaPtrAsInt, CharPtrPtr);
llvm::Value *GPR = Builder.CreateLoad(GPRPtr, false, "gpr");
// Align GPR when TY is i64.
if (isI64) {
@@ -3144,18 +3206,23 @@ llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
GPR = Builder.CreateSelect(CC64, GPRPlusOne, GPR);
}
llvm::Value *FPR = Builder.CreateLoad(FPRPtr, false, "fpr");
- llvm::Value *OverflowArea = Builder.CreateLoad(OverflowAreaPtr, false, "overflow_area");
- llvm::Value *OverflowAreaAsInt = Builder.CreatePtrToInt(OverflowArea, CGF.Int32Ty);
- llvm::Value *RegsaveArea = Builder.CreateLoad(RegsaveAreaPtr, false, "regsave_area");
- llvm::Value *RegsaveAreaAsInt = Builder.CreatePtrToInt(RegsaveArea, CGF.Int32Ty);
+ llvm::Value *OverflowArea =
+ Builder.CreateLoad(OverflowAreaPtr, false, "overflow_area");
+ llvm::Value *OverflowAreaAsInt =
+ Builder.CreatePtrToInt(OverflowArea, CGF.Int32Ty);
+ llvm::Value *RegsaveArea =
+ Builder.CreateLoad(RegsaveAreaPtr, false, "regsave_area");
+ llvm::Value *RegsaveAreaAsInt =
+ Builder.CreatePtrToInt(RegsaveArea, CGF.Int32Ty);
- llvm::Value *CC = Builder.CreateICmpULT(isInt ? GPR : FPR,
- Builder.getInt8(8), "cond");
+ llvm::Value *CC =
+ Builder.CreateICmpULT(isInt ? GPR : FPR, Builder.getInt8(8), "cond");
- llvm::Value *RegConstant = Builder.CreateMul(isInt ? GPR : FPR,
- Builder.getInt8(isInt ? 4 : 8));
+ llvm::Value *RegConstant =
+ Builder.CreateMul(isInt ? GPR : FPR, Builder.getInt8(isInt ? 4 : 8));
- llvm::Value *OurReg = Builder.CreateAdd(RegsaveAreaAsInt, Builder.CreateSExt(RegConstant, CGF.Int32Ty));
+ llvm::Value *OurReg = Builder.CreateAdd(
+ RegsaveAreaAsInt, Builder.CreateSExt(RegConstant, CGF.Int32Ty));
if (Ty->isFloatingType())
OurReg = Builder.CreateAdd(OurReg, Builder.getInt32(32));
@@ -3184,8 +3251,10 @@ llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
// Increase the overflow area.
llvm::Value *Result2 = Builder.CreateIntToPtr(OverflowAreaAsInt, PTy);
- OverflowAreaAsInt = Builder.CreateAdd(OverflowAreaAsInt, Builder.getInt32(isInt ? 4 : 8));
- Builder.CreateStore(Builder.CreateIntToPtr(OverflowAreaAsInt, CharPtr), OverflowAreaPtr);
+ OverflowAreaAsInt =
+ Builder.CreateAdd(OverflowAreaAsInt, Builder.getInt32(isInt ? 4 : 8));
+ Builder.CreateStore(Builder.CreateIntToPtr(OverflowAreaAsInt, CharPtr),
+ OverflowAreaPtr);
CGF.EmitBranch(Cont);
CGF.EmitBlock(Cont);
@@ -3195,7 +3264,7 @@ llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
Result->addIncoming(Result2, UsingOverflow);
if (Ty->isAggregateType()) {
- llvm::Value *AGGPtr = Builder.CreateBitCast(Result, CharPtrPtr, "aggrptr") ;
+ llvm::Value *AGGPtr = Builder.CreateBitCast(Result, CharPtrPtr, "aggrptr");
return Builder.CreateLoad(AGGPtr, false, "aggr");
}
@@ -3257,13 +3326,42 @@ public:
private:
static const unsigned GPRBits = 64;
ABIKind Kind;
+ bool HasQPX;
+
+ // A vector of float or double will be promoted to <4 x f32> or <4 x f64> and
+ // will be passed in a QPX register.
+ bool IsQPXVectorTy(const Type *Ty) const {
+ if (!HasQPX)
+ return false;
+
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ unsigned NumElements = VT->getNumElements();
+ if (NumElements == 1)
+ return false;
+
+ if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::Double)) {
+ if (getContext().getTypeSize(Ty) <= 256)
+ return true;
+ } else if (VT->getElementType()->
+ isSpecificBuiltinType(BuiltinType::Float)) {
+ if (getContext().getTypeSize(Ty) <= 128)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool IsQPXVectorTy(QualType Ty) const {
+ return IsQPXVectorTy(Ty.getTypePtr());
+ }
public:
- PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind)
- : DefaultABIInfo(CGT), Kind(Kind) {}
+ PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX)
+ : DefaultABIInfo(CGT), Kind(Kind), HasQPX(HasQPX) {}
bool isPromotableTypeForABI(QualType Ty) const;
- bool isAlignedParamType(QualType Ty) const;
+ bool isAlignedParamType(QualType Ty, bool &Align32) const;
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType Ty) const;
@@ -3288,7 +3386,8 @@ public:
const Type *T = isSingleElementStruct(I.type, getContext());
if (T) {
const BuiltinType *BT = T->getAs<BuiltinType>();
- if ((T->isVectorType() && getContext().getTypeSize(T) == 128) ||
+ if (IsQPXVectorTy(T) ||
+ (T->isVectorType() && getContext().getTypeSize(T) == 128) ||
(BT && BT->isFloatingPoint())) {
QualType QT(T, 0);
I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT));
@@ -3304,10 +3403,11 @@ public:
};
class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
+
public:
PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT,
- PPC64_SVR4_ABIInfo::ABIKind Kind)
- : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind)) {}
+ PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX)
+ : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
// This is recovered from gcc output.
@@ -3316,10 +3416,6 @@ public:
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override;
-
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return 16; // Natural alignment for Altivec and VSX vectors.
- }
};
class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
@@ -3333,10 +3429,6 @@ public:
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override;
-
- unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
- return 16; // Natural alignment for Altivec vectors.
- }
};
}
@@ -3370,15 +3462,23 @@ PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const {
/// isAlignedParamType - Determine whether a type requires 16-byte
/// alignment in the parameter area.
bool
-PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty) const {
+PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty, bool &Align32) const {
+ Align32 = false;
+
// Complex types are passed just like their elements.
if (const ComplexType *CTy = Ty->getAs<ComplexType>())
Ty = CTy->getElementType();
// Only vector types of size 16 bytes need alignment (larger types are
// passed via reference, smaller types are not aligned).
- if (Ty->isVectorType())
+ if (IsQPXVectorTy(Ty)) {
+ if (getContext().getTypeSize(Ty) > 128)
+ Align32 = true;
+
+ return true;
+ } else if (Ty->isVectorType()) {
return getContext().getTypeSize(Ty) == 128;
+ }
// For single-element float/vector structs, we consider the whole type
// to have the same alignment requirements as its single element.
@@ -3386,7 +3486,7 @@ PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty) const {
const Type *EltType = isSingleElementStruct(Ty, getContext());
if (EltType) {
const BuiltinType *BT = EltType->getAs<BuiltinType>();
- if ((EltType->isVectorType() &&
+ if (IsQPXVectorTy(EltType) || (EltType->isVectorType() &&
getContext().getTypeSize(EltType) == 128) ||
(BT && BT->isFloatingPoint()))
AlignAsType = EltType;
@@ -3400,13 +3500,22 @@ PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty) const {
AlignAsType = Base;
// With special case aggregates, only vector base types need alignment.
- if (AlignAsType)
+ if (AlignAsType && IsQPXVectorTy(AlignAsType)) {
+ if (getContext().getTypeSize(AlignAsType) > 128)
+ Align32 = true;
+
+ return true;
+ } else if (AlignAsType) {
return AlignAsType->isVectorType();
+ }
// Otherwise, we only need alignment for any aggregate type that
// has an alignment requirement of >= 16 bytes.
- if (isAggregateTypeForABI(Ty) && getContext().getTypeAlign(Ty) >= 128)
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeAlign(Ty) >= 128) {
+ if (HasQPX && getContext().getTypeAlign(Ty) >= 256)
+ Align32 = true;
return true;
+ }
return false;
}
@@ -3512,7 +3621,7 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
return true;
}
if (const VectorType *VT = Ty->getAs<VectorType>()) {
- if (getContext().getTypeSize(VT) == 128)
+ if (getContext().getTypeSize(VT) == 128 || IsQPXVectorTy(Ty))
return true;
}
return false;
@@ -3538,7 +3647,7 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
// Non-Altivec vector types are passed in GPRs (smaller than 16 bytes)
// or via reference (larger than 16 bytes).
- if (Ty->isVectorType()) {
+ if (Ty->isVectorType() && !IsQPXVectorTy(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);
if (Size > 128)
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
@@ -3552,7 +3661,9 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
- uint64_t ABIAlign = isAlignedParamType(Ty)? 16 : 8;
+ bool Align32;
+ uint64_t ABIAlign = isAlignedParamType(Ty, Align32) ?
+ (Align32 ? 32 : 16) : 8;
uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
// ELFv2 homogeneous aggregates are passed as array types.
@@ -3609,7 +3720,7 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
// Non-Altivec vector types are returned in GPRs (smaller than 16 bytes)
// or via reference (larger than 16 bytes).
- if (RetTy->isVectorType()) {
+ if (RetTy->isVectorType() && !IsQPXVectorTy(RetTy)) {
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size > 128)
return ABIArgInfo::getIndirect(0);
@@ -3666,10 +3777,13 @@ llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
// Handle types that require 16-byte alignment in the parameter save area.
- if (isAlignedParamType(Ty)) {
+ bool Align32;
+ if (isAlignedParamType(Ty, Align32)) {
llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
- AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt64(15));
- AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt64(-16));
+ AddrAsInt = Builder.CreateAdd(AddrAsInt,
+ Builder.getInt64(Align32 ? 31 : 15));
+ AddrAsInt = Builder.CreateAnd(AddrAsInt,
+ Builder.getInt64(Align32 ? -32 : -16));
Addr = Builder.CreateIntToPtr(AddrAsInt, BP, "ap.align");
}
@@ -3704,8 +3818,10 @@ llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
llvm::Value *RealAddr = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
llvm::Value *ImagAddr = RealAddr;
if (CGF.CGM.getDataLayout().isBigEndian()) {
- RealAddr = Builder.CreateAdd(RealAddr, Builder.getInt64(8 - CplxBaseSize));
- ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(16 - CplxBaseSize));
+ RealAddr =
+ Builder.CreateAdd(RealAddr, Builder.getInt64(8 - CplxBaseSize));
+ ImagAddr =
+ Builder.CreateAdd(ImagAddr, Builder.getInt64(16 - CplxBaseSize));
} else {
ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(8));
}
@@ -3714,10 +3830,12 @@ llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
ImagAddr = Builder.CreateIntToPtr(ImagAddr, PBaseTy);
llvm::Value *Real = Builder.CreateLoad(RealAddr, false, ".vareal");
llvm::Value *Imag = Builder.CreateLoad(ImagAddr, false, ".vaimag");
- llvm::Value *Ptr = CGF.CreateTempAlloca(CGT.ConvertTypeForMem(Ty),
- "vacplx");
- llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, ".real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, ".imag");
+ llvm::AllocaInst *Ptr =
+ CGF.CreateTempAlloca(CGT.ConvertTypeForMem(Ty), "vacplx");
+ llvm::Value *RealPtr =
+ Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 0, ".real");
+ llvm::Value *ImagPtr =
+ Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 1, ".imag");
Builder.CreateStore(Real, RealPtr, false);
Builder.CreateStore(Imag, ImagPtr, false);
return Ptr;
@@ -3837,8 +3955,8 @@ private:
llvm::Value *EmitAAPCSVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override {
+ llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const override {
return isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
: EmitAAPCSVAArg(VAListAddr, Ty, CGF);
}
@@ -3849,13 +3967,15 @@ public:
AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind)
: TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {}
- StringRef getARCRetainAutoreleasedReturnValueMarker() const {
+ StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
return "mov\tfp, fp\t\t; marker for objc_retainAutoreleaseReturnValue";
}
- int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { return 31; }
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
+ return 31;
+ }
- virtual bool doesReturnSlotInterfereWithArgs() const { return false; }
+ bool doesReturnSlotInterfereWithArgs() const override { return false; }
};
}
@@ -3964,7 +4084,15 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
// Aggregates <= 16 bytes are returned directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 128) {
+ unsigned Alignment = getContext().getTypeAlign(RetTy);
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
+
+ // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
+ // For aggregates with 16-byte alignment, we use i128.
+ if (Alignment < 128 && Size == 128) {
+ llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
+ }
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
@@ -4047,13 +4175,15 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
int RegSize = IsIndirect ? 8 : getContext().getTypeSize(Ty) / 8;
if (!IsFPR) {
// 3 is the field number of __gr_offs
- reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 3, "gr_offs_p");
+ reg_offs_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "gr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs");
reg_top_index = 1; // field number for __gr_top
RegSize = llvm::RoundUpToAlignment(RegSize, 8);
} else {
// 4 is the field number of __vr_offs.
- reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 4, "vr_offs_p");
+ reg_offs_p =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 4, "vr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs");
reg_top_index = 2; // field number for __vr_top
RegSize = 16 * NumRegs;
@@ -4114,8 +4244,8 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
CGF.EmitBlock(InRegBlock);
llvm::Value *reg_top_p = nullptr, *reg_top = nullptr;
- reg_top_p =
- CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p");
+ reg_top_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, reg_top_index,
+ "reg_top_p");
reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top");
llvm::Value *BaseAddr = CGF.Builder.CreateGEP(reg_top, reg_offs);
llvm::Value *RegAddr = nullptr;
@@ -4138,7 +4268,7 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
assert(!IsIndirect && "Homogeneous aggregates should be passed directly");
llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0));
llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
- llvm::Value *Tmp = CGF.CreateTempAlloca(HFATy);
+ llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(HFATy);
int Offset = 0;
if (CGF.CGM.getDataLayout().isBigEndian() && Ctx.getTypeSize(Base) < 128)
@@ -4149,7 +4279,8 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
llvm::Value *LoadAddr = CGF.Builder.CreateGEP(BaseAddr, BaseOffset);
LoadAddr = CGF.Builder.CreateBitCast(
LoadAddr, llvm::PointerType::getUnqual(BaseTy));
- llvm::Value *StoreAddr = CGF.Builder.CreateStructGEP(Tmp, i);
+ llvm::Value *StoreAddr =
+ CGF.Builder.CreateStructGEP(Tmp->getAllocatedType(), Tmp, i);
llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr);
CGF.Builder.CreateStore(Elem, StoreAddr);
@@ -4182,7 +4313,7 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
CGF.EmitBlock(OnStackBlock);
llvm::Value *stack_p = nullptr, *OnStackAddr = nullptr;
- stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p");
+ stack_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "stack_p");
OnStackAddr = CGF.Builder.CreateLoad(stack_p, "stack");
// Again, stack arguments may need realigmnent. In this case both integer and
@@ -4248,8 +4379,9 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
return ResAddr;
}
-llvm::Value *AArch64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
+llvm::Value *AArch64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr,
+ QualType Ty,
+ CodeGenFunction &CGF) const {
// We do not support va_arg for aggregates or illegal vector types.
// Lower VAArg here for these cases and use the LLVM va_arg instruction for
// other cases.
@@ -4324,17 +4456,10 @@ public:
private:
ABIKind Kind;
- mutable int VFPRegs[16];
- const unsigned NumVFPs;
- const unsigned NumGPRs;
- mutable unsigned AllocatedGPRs;
- mutable unsigned AllocatedVFPs;
public:
- ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind),
- NumVFPs(16), NumGPRs(4) {
+ ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {
setCCs();
- resetAllocatedRegs();
}
bool isEABI() const {
@@ -4364,8 +4489,7 @@ public:
private:
ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const;
- ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic,
- bool &IsCPRC) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic) const;
bool isIllegalVectorType(QualType Ty) const;
bool isHomogeneousAggregateBaseType(QualType Ty) const override;
@@ -4380,10 +4504,6 @@ private:
llvm::CallingConv::ID getLLVMDefaultCC() const;
llvm::CallingConv::ID getABIDefaultCC() const;
void setCCs();
-
- void markAllocatedGPRs(unsigned Alignment, unsigned NumRequired) const;
- void markAllocatedVFPs(unsigned Alignment, unsigned NumRequired) const;
- void resetAllocatedRegs(void) const;
};
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -4417,7 +4537,7 @@ public:
return TargetCodeGenInfo::getSizeOfUnwindException();
}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
@@ -4456,55 +4576,44 @@ public:
}
};
+class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {
+ void addStackProbeSizeTargetAttribute(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const;
+
+public:
+ WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K)
+ : ARMTargetCodeGenInfo(CGT, K) {}
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override;
+};
+
+void WindowsARMTargetCodeGenInfo::addStackProbeSizeTargetAttribute(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ if (!isa<FunctionDecl>(D))
+ return;
+ if (CGM.getCodeGenOpts().StackProbeSize == 4096)
+ return;
+
+ llvm::Function *F = cast<llvm::Function>(GV);
+ F->addFnAttr("stack-probe-size",
+ llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
+}
+
+void WindowsARMTargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ addStackProbeSizeTargetAttribute(D, GV, CGM);
+}
}
void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
- // To correctly handle Homogeneous Aggregate, we need to keep track of the
- // VFP registers allocated so far.
- // C.1.vfp If the argument is a VFP CPRC and there are sufficient consecutive
- // VFP registers of the appropriate type unallocated then the argument is
- // allocated to the lowest-numbered sequence of such registers.
- // C.2.vfp If the argument is a VFP CPRC then any VFP registers that are
- // unallocated are marked as unavailable.
- resetAllocatedRegs();
-
- if (getCXXABI().classifyReturnType(FI)) {
- if (FI.getReturnInfo().isIndirect())
- markAllocatedGPRs(1, 1);
- } else {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic());
- }
- for (auto &I : FI.arguments()) {
- unsigned PreAllocationVFPs = AllocatedVFPs;
- unsigned PreAllocationGPRs = AllocatedGPRs;
- bool IsCPRC = false;
- // 6.1.2.3 There is one VFP co-processor register class using registers
- // s0-s15 (d0-d7) for passing arguments.
- I.info = classifyArgumentType(I.type, FI.isVariadic(), IsCPRC);
-
- // If we have allocated some arguments onto the stack (due to running
- // out of VFP registers), we cannot split an argument between GPRs and
- // the stack. If this situation occurs, we add padding to prevent the
- // GPRs from being used. In this situation, the current argument could
- // only be allocated by rule C.8, so rule C.6 would mark these GPRs as
- // unusable anyway.
- // We do not have to do this if the argument is being passed ByVal, as the
- // backend can handle that situation correctly.
- const bool StackUsed = PreAllocationGPRs > NumGPRs || PreAllocationVFPs > NumVFPs;
- const bool IsByVal = I.info.isIndirect() && I.info.getIndirectByVal();
- if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs &&
- StackUsed && !IsByVal) {
- llvm::Type *PaddingTy = llvm::ArrayType::get(
- llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
- if (I.info.canHaveCoerceToType()) {
- I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */,
- 0 /* offset */, PaddingTy, true);
- } else {
- I.info = ABIArgInfo::getDirect(nullptr /* type */, 0 /* offset */,
- PaddingTy, true);
- }
- }
- }
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() =
+ classifyReturnType(FI.getReturnType(), FI.isVariadic());
+
+ for (auto &I : FI.arguments())
+ I.info = classifyArgumentType(I.type, FI.isVariadic());
// Always honor user-specified calling convention.
if (FI.getCallingConvention() != llvm::CallingConv::C)
@@ -4512,7 +4621,7 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
llvm::CallingConv::ID cc = getRuntimeCC();
if (cc != llvm::CallingConv::C)
- FI.setEffectiveCallingConvention(cc);
+ FI.setEffectiveCallingConvention(cc);
}
/// Return the default calling convention that LLVM will use.
@@ -4550,64 +4659,8 @@ void ARMABIInfo::setCCs() {
llvm::CallingConv::ARM_APCS : llvm::CallingConv::ARM_AAPCS);
}
-/// markAllocatedVFPs - update VFPRegs according to the alignment and
-/// number of VFP registers (unit is S register) requested.
-void ARMABIInfo::markAllocatedVFPs(unsigned Alignment,
- unsigned NumRequired) const {
- // Early Exit.
- if (AllocatedVFPs >= 16) {
- // We use AllocatedVFP > 16 to signal that some CPRCs were allocated on
- // the stack.
- AllocatedVFPs = 17;
- return;
- }
- // C.1.vfp If the argument is a VFP CPRC and there are sufficient consecutive
- // VFP registers of the appropriate type unallocated then the argument is
- // allocated to the lowest-numbered sequence of such registers.
- for (unsigned I = 0; I < 16; I += Alignment) {
- bool FoundSlot = true;
- for (unsigned J = I, JEnd = I + NumRequired; J < JEnd; J++)
- if (J >= 16 || VFPRegs[J]) {
- FoundSlot = false;
- break;
- }
- if (FoundSlot) {
- for (unsigned J = I, JEnd = I + NumRequired; J < JEnd; J++)
- VFPRegs[J] = 1;
- AllocatedVFPs += NumRequired;
- return;
- }
- }
- // C.2.vfp If the argument is a VFP CPRC then any VFP registers that are
- // unallocated are marked as unavailable.
- for (unsigned I = 0; I < 16; I++)
- VFPRegs[I] = 1;
- AllocatedVFPs = 17; // We do not have enough VFP registers.
-}
-
-/// Update AllocatedGPRs to record the number of general purpose registers
-/// which have been allocated. It is valid for AllocatedGPRs to go above 4,
-/// this represents arguments being stored on the stack.
-void ARMABIInfo::markAllocatedGPRs(unsigned Alignment,
- unsigned NumRequired) const {
- assert((Alignment == 1 || Alignment == 2) && "Alignment must be 4 or 8 bytes");
-
- if (Alignment == 2 && AllocatedGPRs & 0x1)
- AllocatedGPRs += 1;
-
- AllocatedGPRs += NumRequired;
-}
-
-void ARMABIInfo::resetAllocatedRegs(void) const {
- AllocatedGPRs = 0;
- AllocatedVFPs = 0;
- for (unsigned i = 0; i < NumVFPs; ++i)
- VFPRegs[i] = 0;
-}
-
-ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
- bool &IsCPRC) const {
- // We update number of allocated VFPs according to
+ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
+ bool isVariadic) const {
// 6.1.2.1 The following argument types are VFP CPRCs:
// A single-precision floating-point type (including promoted
// half-precision types); A double-precision floating-point type;
@@ -4625,58 +4678,20 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
if (Size <= 32) {
llvm::Type *ResType =
llvm::Type::getInt32Ty(getVMContext());
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getDirect(ResType);
}
if (Size == 64) {
llvm::Type *ResType = llvm::VectorType::get(
llvm::Type::getInt32Ty(getVMContext()), 2);
- if (getABIKind() == ARMABIInfo::AAPCS || isVariadic){
- markAllocatedGPRs(2, 2);
- } else {
- markAllocatedVFPs(2, 2);
- IsCPRC = true;
- }
return ABIArgInfo::getDirect(ResType);
}
if (Size == 128) {
llvm::Type *ResType = llvm::VectorType::get(
llvm::Type::getInt32Ty(getVMContext()), 4);
- if (getABIKind() == ARMABIInfo::AAPCS || isVariadic) {
- markAllocatedGPRs(2, 4);
- } else {
- markAllocatedVFPs(4, 4);
- IsCPRC = true;
- }
return ABIArgInfo::getDirect(ResType);
}
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
}
- // Update VFPRegs for legal vector types.
- if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) {
- if (const VectorType *VT = Ty->getAs<VectorType>()) {
- uint64_t Size = getContext().getTypeSize(VT);
- // Size of a legal vector should be power of 2 and above 64.
- markAllocatedVFPs(Size >= 128 ? 4 : 2, Size / 32);
- IsCPRC = true;
- }
- }
- // Update VFPRegs for floating point types.
- if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) {
- if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
- if (BT->getKind() == BuiltinType::Half ||
- BT->getKind() == BuiltinType::Float) {
- markAllocatedVFPs(1, 1);
- IsCPRC = true;
- }
- if (BT->getKind() == BuiltinType::Double ||
- BT->getKind() == BuiltinType::LongDouble) {
- markAllocatedVFPs(2, 2);
- IsCPRC = true;
- }
- }
- }
if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
@@ -4684,15 +4699,11 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
Ty = EnumTy->getDecl()->getIntegerType();
}
- unsigned Size = getContext().getTypeSize(Ty);
- if (!IsCPRC)
- markAllocatedGPRs(Size > 32 ? 2 : 1, (Size + 31) / 32);
return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend()
: ABIArgInfo::getDirect());
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
}
@@ -4708,19 +4719,6 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
if (isHomogeneousAggregate(Ty, Base, Members)) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Base can be a floating-point or a vector.
- if (Base->isVectorType()) {
- // ElementSize is in number of floats.
- unsigned ElementSize = getContext().getTypeSize(Base) == 64 ? 2 : 4;
- markAllocatedVFPs(ElementSize,
- Members * ElementSize);
- } else if (Base->isSpecificBuiltinType(BuiltinType::Float))
- markAllocatedVFPs(1, Members);
- else {
- assert(Base->isSpecificBuiltinType(BuiltinType::Double) ||
- Base->isSpecificBuiltinType(BuiltinType::LongDouble));
- markAllocatedVFPs(2, Members * 2);
- }
- IsCPRC = true;
return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
}
}
@@ -4732,15 +4730,11 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
uint64_t ABIAlign = 4;
uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
- getABIKind() == ARMABIInfo::AAPCS)
+ getABIKind() == ARMABIInfo::AAPCS)
ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
+
if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
- // Update Allocated GPRs. Since this is only used when the size of the
- // argument is greater than 64 bytes, this will always use up any available
- // registers (of which there are 4). We also don't care about getting the
- // alignment right, because general-purpose registers cannot be back-filled.
- markAllocatedGPRs(1, 4);
- return ABIArgInfo::getIndirect(TyAlign, /*ByVal=*/true,
+ return ABIArgInfo::getIndirect(ABIAlign, /*ByVal=*/true,
/*Realign=*/TyAlign > ABIAlign);
}
@@ -4752,11 +4746,9 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
if (getContext().getTypeAlign(Ty) <= 32) {
ElemTy = llvm::Type::getInt32Ty(getVMContext());
SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
- markAllocatedGPRs(1, SizeRegs);
} else {
ElemTy = llvm::Type::getInt64Ty(getVMContext());
SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
- markAllocatedGPRs(2, SizeRegs * 2);
}
return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs));
@@ -4856,7 +4848,6 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// Large vector types should be returned via memory.
if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) {
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0);
}
@@ -4894,7 +4885,6 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
}
// Otherwise return in memory.
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0);
}
@@ -4930,7 +4920,6 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
}
- markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0);
}
@@ -5046,42 +5035,6 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return AddrTyped;
}
-namespace {
-
-class NaClARMABIInfo : public ABIInfo {
- public:
- NaClARMABIInfo(CodeGen::CodeGenTypes &CGT, ARMABIInfo::ABIKind Kind)
- : ABIInfo(CGT), PInfo(CGT), NInfo(CGT, Kind) {}
- void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
- private:
- PNaClABIInfo PInfo; // Used for generating calls with pnaclcall callingconv.
- ARMABIInfo NInfo; // Used for everything else.
-};
-
-class NaClARMTargetCodeGenInfo : public TargetCodeGenInfo {
- public:
- NaClARMTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, ARMABIInfo::ABIKind Kind)
- : TargetCodeGenInfo(new NaClARMABIInfo(CGT, Kind)) {}
-};
-
-}
-
-void NaClARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
- if (FI.getASTCallingConvention() == CC_PnaclCall)
- PInfo.computeInfo(FI);
- else
- static_cast<const ABIInfo&>(NInfo).computeInfo(FI);
-}
-
-llvm::Value *NaClARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // Always use the native convention; calling pnacl-style varargs functions
- // is unsupported.
- return static_cast<const ABIInfo&>(NInfo).EmitVAArg(VAListAddr, Ty, CGF);
-}
-
//===----------------------------------------------------------------------===//
// NVPTX ABI Implementation
//===----------------------------------------------------------------------===//
@@ -5105,7 +5058,7 @@ public:
NVPTXTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new NVPTXABIInfo(CGT)) {}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
private:
// Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
@@ -5161,7 +5114,7 @@ llvm::Value *NVPTXABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
}
void NVPTXTargetCodeGenInfo::
-SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const{
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) return;
@@ -5190,18 +5143,22 @@ SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
// Create !{<func-ref>, metadata !"kernel", i32 1} node
addNVVMMetadata(F, "kernel", 1);
}
- if (FD->hasAttr<CUDALaunchBoundsAttr>()) {
+ if (CUDALaunchBoundsAttr *Attr = FD->getAttr<CUDALaunchBoundsAttr>()) {
// Create !{<func-ref>, metadata !"maxntidx", i32 <val>} node
- addNVVMMetadata(F, "maxntidx",
- FD->getAttr<CUDALaunchBoundsAttr>()->getMaxThreads());
- // min blocks is a default argument for CUDALaunchBoundsAttr, so getting a
- // zero value from getMinBlocks either means it was not specified in
- // __launch_bounds__ or the user specified a 0 value. In both cases, we
- // don't have to add a PTX directive.
- int MinCTASM = FD->getAttr<CUDALaunchBoundsAttr>()->getMinBlocks();
- if (MinCTASM > 0) {
- // Create !{<func-ref>, metadata !"minctasm", i32 <val>} node
- addNVVMMetadata(F, "minctasm", MinCTASM);
+ llvm::APSInt MaxThreads(32);
+ MaxThreads = Attr->getMaxThreads()->EvaluateKnownConstInt(M.getContext());
+ if (MaxThreads > 0)
+ addNVVMMetadata(F, "maxntidx", MaxThreads.getExtValue());
+
+ // min blocks is an optional argument for CUDALaunchBoundsAttr. If it was
+ // not specified in __launch_bounds__ or if the user specified a 0 value,
+ // we don't have to add a PTX directive.
+ if (Attr->getMinBlocks()) {
+ llvm::APSInt MinBlocks(32);
+ MinBlocks = Attr->getMinBlocks()->EvaluateKnownConstInt(M.getContext());
+ if (MinBlocks > 0)
+ // Create !{<func-ref>, metadata !"minctasm", i32 <val>} node
+ addNVVMMetadata(F, "minctasm", MinBlocks.getExtValue());
}
}
}
@@ -5231,12 +5188,17 @@ void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::Function *F, StringRef Name,
namespace {
class SystemZABIInfo : public ABIInfo {
+ bool HasVector;
+
public:
- SystemZABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
+ SystemZABIInfo(CodeGenTypes &CGT, bool HV)
+ : ABIInfo(CGT), HasVector(HV) {}
bool isPromotableIntegerType(QualType Ty) const;
bool isCompoundType(QualType Ty) const;
+ bool isVectorArgumentType(QualType Ty) const;
bool isFPArgumentType(QualType Ty) const;
+ QualType GetSingleElementType(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType ArgTy) const;
@@ -5254,8 +5216,8 @@ public:
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- SystemZTargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(new SystemZABIInfo(CGT)) {}
+ SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+ : TargetCodeGenInfo(new SystemZABIInfo(CGT, HasVector)) {}
};
}
@@ -5282,7 +5244,15 @@ bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const {
}
bool SystemZABIInfo::isCompoundType(QualType Ty) const {
- return Ty->isAnyComplexType() || isAggregateTypeForABI(Ty);
+ return (Ty->isAnyComplexType() ||
+ Ty->isVectorType() ||
+ isAggregateTypeForABI(Ty));
+}
+
+bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const {
+ return (HasVector &&
+ Ty->isVectorType() &&
+ getContext().getTypeSize(Ty) <= 128);
}
bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
@@ -5295,9 +5265,13 @@ bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
return false;
}
+ return false;
+}
+
+QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
if (const RecordType *RT = Ty->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl();
- bool Found = false;
+ QualType Found;
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
@@ -5308,36 +5282,34 @@ bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
if (isEmptyRecord(getContext(), Base, true))
continue;
- if (Found)
- return false;
- Found = isFPArgumentType(Base);
- if (!Found)
- return false;
+ if (!Found.isNull())
+ return Ty;
+ Found = GetSingleElementType(Base);
}
// Check the fields.
for (const auto *FD : RD->fields()) {
- // Empty bitfields don't affect things either way.
+ // For compatibility with GCC, ignore empty bitfields in C++ mode.
// Unlike isSingleElementStruct(), empty structure and array fields
// do count. So do anonymous bitfields that aren't zero-sized.
- if (FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
- return true;
+ if (getContext().getLangOpts().CPlusPlus &&
+ FD->isBitField() && FD->getBitWidthValue(getContext()) == 0)
+ continue;
// Unlike isSingleElementStruct(), arrays do not count.
- // Nested isFPArgumentType structures still do though.
- if (Found)
- return false;
- Found = isFPArgumentType(FD->getType());
- if (!Found)
- return false;
+ // Nested structures still do though.
+ if (!Found.isNull())
+ return Ty;
+ Found = GetSingleElementType(FD->getType());
}
// Unlike isSingleElementStruct(), trailing padding is allowed.
// An 8-byte aligned struct s { float f; } is passed as a double.
- return Found;
+ if (!Found.isNull())
+ return Found;
}
- return false;
+ return Ty;
}
llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -5350,26 +5322,56 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// i8 *__reg_save_area;
// };
- // Every argument occupies 8 bytes and is passed by preference in either
- // GPRs or FPRs.
+ // Every non-vector argument occupies 8 bytes and is passed by preference
+ // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are
+ // always passed on the stack.
Ty = CGF.getContext().getCanonicalType(Ty);
+ llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
+ llvm::Type *APTy = llvm::PointerType::getUnqual(ArgTy);
ABIArgInfo AI = classifyArgumentType(Ty);
- bool InFPRs = isFPArgumentType(Ty);
-
- llvm::Type *APTy = llvm::PointerType::getUnqual(CGF.ConvertTypeForMem(Ty));
bool IsIndirect = AI.isIndirect();
+ bool InFPRs = false;
+ bool IsVector = false;
unsigned UnpaddedBitSize;
if (IsIndirect) {
APTy = llvm::PointerType::getUnqual(APTy);
UnpaddedBitSize = 64;
- } else
+ } else {
+ if (AI.getCoerceToType())
+ ArgTy = AI.getCoerceToType();
+ InFPRs = ArgTy->isFloatTy() || ArgTy->isDoubleTy();
+ IsVector = ArgTy->isVectorTy();
UnpaddedBitSize = getContext().getTypeSize(Ty);
- unsigned PaddedBitSize = 64;
+ }
+ unsigned PaddedBitSize = (IsVector && UnpaddedBitSize > 64) ? 128 : 64;
assert((UnpaddedBitSize <= PaddedBitSize) && "Invalid argument size.");
unsigned PaddedSize = PaddedBitSize / 8;
unsigned Padding = (PaddedBitSize - UnpaddedBitSize) / 8;
+ llvm::Type *IndexTy = CGF.Int64Ty;
+ llvm::Value *PaddedSizeV = llvm::ConstantInt::get(IndexTy, PaddedSize);
+
+ if (IsVector) {
+ // Work out the address of a vector argument on the stack.
+ // Vector arguments are always passed in the high bits of a
+ // single (8 byte) or double (16 byte) stack slot.
+ llvm::Value *OverflowArgAreaPtr =
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 2,
+ "overflow_arg_area_ptr");
+ llvm::Value *OverflowArgArea =
+ CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area");
+ llvm::Value *MemAddr =
+ CGF.Builder.CreateBitCast(OverflowArgArea, APTy, "mem_addr");
+
+ // Update overflow_arg_area_ptr pointer
+ llvm::Value *NewOverflowArgArea =
+ CGF.Builder.CreateGEP(OverflowArgArea, PaddedSizeV, "overflow_arg_area");
+ CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
+
+ return MemAddr;
+ }
+
unsigned MaxRegs, RegCountField, RegSaveIndex, RegPadding;
if (InFPRs) {
MaxRegs = 4; // Maximum of 4 FPR arguments
@@ -5383,10 +5385,9 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
RegPadding = Padding; // values are passed in the low bits of a GPR
}
- llvm::Value *RegCountPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr");
+ llvm::Value *RegCountPtr = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, RegCountField, "reg_count_ptr");
llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");
- llvm::Type *IndexTy = RegCount->getType();
llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);
llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV,
"fits_in_regs");
@@ -5400,7 +5401,6 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CGF.EmitBlock(InRegBlock);
// Work out the address of an argument register.
- llvm::Value *PaddedSizeV = llvm::ConstantInt::get(IndexTy, PaddedSize);
llvm::Value *ScaledRegCount =
CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count");
llvm::Value *RegBase =
@@ -5408,7 +5408,7 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *RegOffset =
CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");
llvm::Value *RegSaveAreaPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");
+ CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "reg_save_area_ptr");
llvm::Value *RegSaveArea =
CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
llvm::Value *RawRegAddr =
@@ -5427,8 +5427,8 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CGF.EmitBlock(InMemBlock);
// Work out the address of a stack argument.
- llvm::Value *OverflowArgAreaPtr =
- CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
+ llvm::Value *OverflowArgAreaPtr = CGF.Builder.CreateStructGEP(
+ nullptr, VAListAddr, 2, "overflow_arg_area_ptr");
llvm::Value *OverflowArgArea =
CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area");
llvm::Value *PaddingV = llvm::ConstantInt::get(IndexTy, Padding);
@@ -5458,6 +5458,8 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
+ if (isVectorArgumentType(RetTy))
+ return ABIArgInfo::getDirect();
if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)
return ABIArgInfo::getIndirect(0);
return (isPromotableIntegerType(RetTy) ?
@@ -5473,8 +5475,16 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
if (isPromotableIntegerType(Ty))
return ABIArgInfo::getExtend();
- // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
+ // Handle vector types and vector-like structure types. Note that
+ // as opposed to float-like structure types, we do not allow any
+ // padding for vector-like structures, so verify the sizes match.
uint64_t Size = getContext().getTypeSize(Ty);
+ QualType SingleElementTy = GetSingleElementType(Ty);
+ if (isVectorArgumentType(SingleElementTy) &&
+ getContext().getTypeSize(SingleElementTy) == Size)
+ return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy));
+
+ // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
@@ -5488,7 +5498,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// The structure is passed as an unextended integer, a float, or a double.
llvm::Type *PassTy;
- if (isFPArgumentType(Ty)) {
+ if (isFPArgumentType(SingleElementTy)) {
assert(Size == 32 || Size == 64);
if (Size == 32)
PassTy = llvm::Type::getFloatTy(getVMContext());
@@ -5516,13 +5526,13 @@ class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
public:
MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
};
}
-void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+void MSP430TargetCodeGenInfo::setTargetAttributes(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -5568,6 +5578,7 @@ public:
void computeInfo(CGFunctionInfo &FI) const override;
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const override;
+ bool shouldSignExtUnsignedType(QualType Ty) const override;
};
class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -5581,7 +5592,7 @@ public:
return 29;
}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) return;
@@ -5603,8 +5614,8 @@ public:
};
}
-void MipsABIInfo::CoerceToIntArgs(uint64_t TySize,
- SmallVectorImpl<llvm::Type *> &ArgList) const {
+void MipsABIInfo::CoerceToIntArgs(
+ uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
llvm::IntegerType *IntTy =
llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
@@ -5643,7 +5654,7 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
const RecordDecl *RD = RT->getDecl();
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
-
+
uint64_t LastOffset = 0;
unsigned idx = 0;
llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
@@ -5745,7 +5756,7 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
// 1. The size of the struct/class is no larger than 128-bit.
// 2. The struct/class has one or two fields all of which are floating
// point types.
- // 3. The offset of the first field is zero (this follows what gcc does).
+ // 3. The offset of the first field is zero (this follows what gcc does).
//
// Any other composite results are returned in integer registers.
//
@@ -5815,7 +5826,7 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
if (!getCXXABI().classifyReturnType(FI))
RetInfo = classifyReturnType(FI.getReturnType());
- // Check if a pointer to an aggregate is passed as a hidden argument.
+ // Check if a pointer to an aggregate is passed as a hidden argument.
uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
for (auto &I : FI.arguments())
@@ -5837,7 +5848,7 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
Ty = CGF.getContext().getIntTypeForBitwidth(SlotSizeInBits,
Ty->isSignedIntegerType());
}
-
+
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
@@ -5856,7 +5867,7 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
AddrTyped = CGF.Builder.CreateIntToPtr(And, PTy);
}
else
- AddrTyped = Builder.CreateBitCast(Addr, PTy);
+ AddrTyped = Builder.CreateBitCast(Addr, PTy);
llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP);
TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes);
@@ -5866,10 +5877,20 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset),
"ap.next");
Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
+
return AddrTyped;
}
+bool MipsABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
+ int TySize = getContext().getTypeSize(Ty);
+
+ // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
+ if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
+ return true;
+
+ return false;
+}
+
bool
MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const {
@@ -5900,7 +5921,7 @@ MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
//===----------------------------------------------------------------------===//
// TCE ABI Implementation (see http://tce.cs.tut.fi). Uses mostly the defaults.
-// Currently subclassed only to implement custom OpenCL C function attribute
+// Currently subclassed only to implement custom OpenCL C function attribute
// handling.
//===----------------------------------------------------------------------===//
@@ -5911,18 +5932,17 @@ public:
TCETargetCodeGenInfo(CodeGenTypes &CGT)
: DefaultTargetCodeGenInfo(CGT) {}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
};
-void TCETargetCodeGenInfo::SetTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const {
+void TCETargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) return;
llvm::Function *F = cast<llvm::Function>(GV);
-
+
if (M.getLangOpts().OpenCL) {
if (FD->hasAttr<OpenCLKernelAttr>()) {
// OpenCL C Kernel functions are not subject to inlining
@@ -5931,8 +5951,9 @@ void TCETargetCodeGenInfo::SetTargetAttributes(const Decl *D,
if (Attr) {
// Convert the reqd_work_group_size() attributes to metadata.
llvm::LLVMContext &Context = F->getContext();
- llvm::NamedMDNode *OpenCLMetadata =
- M.getModule().getOrInsertNamedMetadata("opencl.kernel_wg_size_info");
+ llvm::NamedMDNode *OpenCLMetadata =
+ M.getModule().getOrInsertNamedMetadata(
+ "opencl.kernel_wg_size_info");
SmallVector<llvm::Metadata *, 5> Operands;
Operands.push_back(llvm::ConstantAsMetadata::get(F));
@@ -5947,9 +5968,9 @@ void TCETargetCodeGenInfo::SetTargetAttributes(const Decl *D,
llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue(
M.Int32Ty, llvm::APInt(32, Attr->getZDim()))));
- // Add a boolean constant operand for "required" (true) or "hint" (false)
- // for implementing the work_group_size_hint attr later. Currently
- // always true as the hint is not yet implemented.
+ // Add a boolean constant operand for "required" (true) or "hint"
+ // (false) for implementing the work_group_size_hint attr later.
+ // Currently always true as the hint is not yet implemented.
Operands.push_back(
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getTrue(Context)));
OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Operands));
@@ -6103,13 +6124,13 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
};
}
-void AMDGPUTargetCodeGenInfo::SetTargetAttributes(
+void AMDGPUTargetCodeGenInfo::setTargetAttributes(
const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {
@@ -6264,12 +6285,7 @@ private:
// Check if Ty is a usable substitute for the coercion type.
bool isUsableType(llvm::StructType *Ty) const {
- if (Ty->getNumElements() != Elems.size())
- return false;
- for (unsigned i = 0, e = Elems.size(); i != e; ++i)
- if (Elems[i] != Ty->getElementType(i))
- return false;
- return true;
+ return llvm::makeArrayRef(Elems) == Ty->elements();
}
// Get the coercion type as a literal struct type.
@@ -6430,7 +6446,7 @@ SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
// FSR = 70
// CSR = 71
AssignToArrayRange(Builder, Address, Eight8, 64, 71);
-
+
// 72-87: d0-15, the 8-byte floating-point registers
AssignToArrayRange(Builder, Address, Eight8, 72, 87);
@@ -6703,7 +6719,7 @@ StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
///
/// The TypeString carries type, qualifier, name, size & value details.
/// Please see 'Tools Development Guide' section 2.16.2 for format details:
-/// <https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf>
+/// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf
/// The output is tested by test/CodeGen/xcore-stringtype.c.
///
static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
@@ -6729,7 +6745,8 @@ static bool appendType(SmallStringEnc &Enc, QualType QType,
TypeStringCache &TSC);
/// Helper function for appendRecordType().
-/// Builds a SmallVector containing the encoded field types in declaration order.
+/// Builds a SmallVector containing the encoded field types in declaration
+/// order.
static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
const RecordDecl *RD,
const CodeGen::CodeGenModule &CGM,
@@ -6752,7 +6769,7 @@ static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
if (Field->isBitField())
Enc += ')';
Enc += '}';
- FE.push_back(FieldEncoding(!Field->getName().empty(), Enc));
+ FE.emplace_back(!Field->getName().empty(), Enc);
}
return true;
}
@@ -7082,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:
@@ -7102,6 +7121,12 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
{
+ if (Triple.getOS() == llvm::Triple::Win32) {
+ TheTargetCodeGenInfo =
+ new WindowsARMTargetCodeGenInfo(Types, ARMABIInfo::AAPCS_VFP);
+ return *TheTargetCodeGenInfo;
+ }
+
ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS;
if (getTarget().getABI() == "apcs-gnu")
Kind = ARMABIInfo::APCS;
@@ -7110,14 +7135,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
Triple.getEnvironment() == llvm::Triple::GNUEABIHF))
Kind = ARMABIInfo::AAPCS_VFP;
- switch (Triple.getOS()) {
- case llvm::Triple::NaCl:
- return *(TheTargetCodeGenInfo =
- new NaClARMTargetCodeGenInfo(Types, Kind));
- default:
- return *(TheTargetCodeGenInfo =
- new ARMTargetCodeGenInfo(Types, Kind));
- }
+ return *(TheTargetCodeGenInfo = new ARMTargetCodeGenInfo(Types, Kind));
}
case llvm::Triple::ppc:
@@ -7127,19 +7145,21 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1;
if (getTarget().getABI() == "elfv2")
Kind = PPC64_SVR4_ABIInfo::ELFv2;
+ bool HasQPX = getTarget().getABI() == "elfv1-qpx";
return *(TheTargetCodeGenInfo =
- new PPC64_SVR4_TargetCodeGenInfo(Types, Kind));
+ new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX));
} else
return *(TheTargetCodeGenInfo = new PPC64TargetCodeGenInfo(Types));
case llvm::Triple::ppc64le: {
assert(Triple.isOSBinFormatELF() && "PPC64 LE non-ELF not supported!");
PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv2;
- if (getTarget().getABI() == "elfv1")
+ if (getTarget().getABI() == "elfv1" || getTarget().getABI() == "elfv1-qpx")
Kind = PPC64_SVR4_ABIInfo::ELFv1;
+ bool HasQPX = getTarget().getABI() == "elfv1-qpx";
return *(TheTargetCodeGenInfo =
- new PPC64_SVR4_TargetCodeGenInfo(Types, Kind));
+ new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX));
}
case llvm::Triple::nvptx:
@@ -7149,8 +7169,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::msp430:
return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types));
- case llvm::Triple::systemz:
- return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types));
+ case llvm::Triple::systemz: {
+ bool HasVector = getTarget().getABI() == "vector";
+ return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types,
+ HasVector));
+ }
case llvm::Triple::tce:
return *(TheTargetCodeGenInfo = new TCETargetCodeGenInfo(Types));
@@ -7162,33 +7185,32 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing();
if (Triple.getOS() == llvm::Triple::Win32) {
- return *(TheTargetCodeGenInfo =
- new WinX86_32TargetCodeGenInfo(Types,
- IsDarwinVectorABI, IsSmallStructInRegABI,
- IsWin32FloatStructABI,
- CodeGenOpts.NumRegisterParameters));
+ return *(TheTargetCodeGenInfo = new WinX86_32TargetCodeGenInfo(
+ Types, IsDarwinVectorABI, IsSmallStructInRegABI,
+ IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters));
} else {
- return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types,
- IsDarwinVectorABI, IsSmallStructInRegABI,
- IsWin32FloatStructABI,
- CodeGenOpts.NumRegisterParameters));
+ return *(TheTargetCodeGenInfo = new X86_32TargetCodeGenInfo(
+ Types, IsDarwinVectorABI, IsSmallStructInRegABI,
+ IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters));
}
}
case llvm::Triple::x86_64: {
- bool HasAVX = getTarget().getABI() == "avx";
+ StringRef ABI = getTarget().getABI();
+ X86AVXABILevel AVXLevel = (ABI == "avx512" ? X86AVXABILevel::AVX512 :
+ ABI == "avx" ? X86AVXABILevel::AVX :
+ X86AVXABILevel::None);
switch (Triple.getOS()) {
case llvm::Triple::Win32:
return *(TheTargetCodeGenInfo =
- new WinX86_64TargetCodeGenInfo(Types, HasAVX));
- case llvm::Triple::NaCl:
+ new WinX86_64TargetCodeGenInfo(Types, AVXLevel));
+ case llvm::Triple::PS4:
return *(TheTargetCodeGenInfo =
- new NaClX86_64TargetCodeGenInfo(Types, HasAVX));
+ new PS4TargetCodeGenInfo(Types, AVXLevel));
default:
return *(TheTargetCodeGenInfo =
- new X86_64TargetCodeGenInfo(Types, HasAVX));
+ new X86_64TargetCodeGenInfo(Types, AVXLevel));
}
}
case llvm::Triple::hexagon:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
index cc469d6..95275d5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
@@ -53,12 +53,12 @@ public:
/// getABIInfo() - Returns ABI info helper for the target.
const ABIInfo &getABIInfo() const { return *Info; }
- /// SetTargetAttributes - Provides a convenient hook to handle extra
+ /// setTargetAttributes - Provides a convenient hook to handle extra
/// target-specific attributes for the given global.
- virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {}
- /// EmitTargetMD - Provides a convenient hook to handle extra
+ /// emitTargetMD - Provides a convenient hook to handle extra
/// target-specific metadata for the given global.
virtual void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {}
@@ -218,13 +218,6 @@ public:
virtual void getDetectMismatchOption(llvm::StringRef Name,
llvm::StringRef Value,
llvm::SmallString<32> &Opt) const {}
-
- /// Gets the target-specific default alignment used when an 'aligned' clause
- /// is used with a 'simd' OpenMP directive without specifying a specific
- /// alignment.
- virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const {
- return 0;
- }
};
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
index 360dbee..3219dc1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
index 2bcbd5c..101d1fc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -192,18 +192,14 @@ static bool InputsOk(const Command &C,
return !ActionFailed(&C.getSource(), FailingCommands);
}
-void Compilation::ExecuteJob(const Job &J,
- FailingCommandList &FailingCommands) const {
- if (const Command *C = dyn_cast<Command>(&J)) {
- if (!InputsOk(*C, FailingCommands))
- return;
+void Compilation::ExecuteJobs(const JobList &Jobs,
+ FailingCommandList &FailingCommands) const {
+ for (const auto &Job : Jobs) {
+ if (!InputsOk(Job, FailingCommands))
+ continue;
const Command *FailingCommand = nullptr;
- if (int Res = ExecuteCommand(*C, FailingCommand))
+ if (int Res = ExecuteCommand(Job, FailingCommand))
FailingCommands.push_back(std::make_pair(Res, FailingCommand));
- } else {
- const JobList *Jobs = cast<JobList>(&J);
- for (const auto &Job : *Jobs)
- ExecuteJob(Job, FailingCommands);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
index 03fe41b..ffb1469 100644
--- a/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
@@ -60,7 +60,7 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> ResourceDir(D.ResourceDir);
llvm::sys::path::append(ResourceDir, "include");
- addSystemInclude(DriverArgs, CC1Args, ResourceDir.str());
+ addSystemInclude(DriverArgs, CC1Args, ResourceDir);
}
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
@@ -108,10 +108,9 @@ AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
}
Tool *CrossWindowsToolChain::buildLinker() const {
- return new tools::CrossWindows::Link(*this);
+ return new tools::CrossWindows::Linker(*this);
}
Tool *CrossWindowsToolChain::buildAssembler() const {
- return new tools::CrossWindows::Assemble(*this);
+ return new tools::CrossWindows::Assembler(*this);
}
-
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index 1664d0d..180c412 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
@@ -44,22 +45,20 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
-Driver::Driver(StringRef ClangExecutable,
- StringRef DefaultTargetTriple,
+Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
DiagnosticsEngine &Diags)
- : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
- ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
- UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
- DriverTitle("clang LLVM compiler"),
- CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
- CCLogDiagnosticsFilename(nullptr),
- CCCPrintBindings(false),
- CCPrintHeaders(false), CCLogDiagnostics(false),
- CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
- CCCUsePCH(true), SuppressMissingInputWarning(false) {
-
- Name = llvm::sys::path::stem(ClangExecutable);
- Dir = llvm::sys::path::parent_path(ClangExecutable);
+ : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
+ SaveTemps(SaveTempsNone), ClangExecutable(ClangExecutable),
+ SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
+ DefaultTargetTriple(DefaultTargetTriple),
+ DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
+ CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
+ CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+ CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
+ CCCUsePCH(true), SuppressMissingInputWarning(false) {
+
+ Name = llvm::sys::path::filename(ClangExecutable);
+ Dir = llvm::sys::path::parent_path(ClangExecutable);
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
@@ -82,23 +81,23 @@ Driver::~Driver() {
void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
const std::string OptName =
- getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+ getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
- for (size_t I = 0, E = Args.size(); I != E; ++I) {
+ for (const char *ArgPtr : Args) {
// Ingore nullptrs, they are response file's EOL markers
- if (Args[I] == nullptr)
+ if (ArgPtr == nullptr)
continue;
- const StringRef Arg = Args[I];
+ const StringRef Arg = ArgPtr;
if (!Arg.startswith(OptName))
continue;
const StringRef Value = Arg.drop_front(OptName.size());
const unsigned M = llvm::StringSwitch<unsigned>(Value)
- .Case("gcc", GCCMode)
- .Case("g++", GXXMode)
- .Case("cpp", CPPMode)
- .Case("cl", CLMode)
- .Default(~0U);
+ .Case("gcc", GCCMode)
+ .Case("g++", GXXMode)
+ .Case("cpp", CPPMode)
+ .Case("cl", CLMode)
+ .Default(~0U);
if (M != ~0U)
Mode = static_cast<DriverMode>(M);
@@ -107,44 +106,39 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
}
}
-InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
+InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks();
unsigned MissingArgIndex, MissingArgCount;
- InputArgList *Args = getOpts().ParseArgs(ArgStrings.begin(), ArgStrings.end(),
- MissingArgIndex, MissingArgCount,
- IncludedFlagsBitmask,
- ExcludedFlagsBitmask);
+ InputArgList Args =
+ getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount,
+ IncludedFlagsBitmask, ExcludedFlagsBitmask);
// Check for missing argument error.
if (MissingArgCount)
Diag(clang::diag::err_drv_missing_argument)
- << Args->getArgString(MissingArgIndex) << MissingArgCount;
+ << Args.getArgString(MissingArgIndex) << MissingArgCount;
// Check for unsupported options.
- for (const Arg *A : *Args) {
+ for (const Arg *A : Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
- Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
+ Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(Args);
continue;
}
// Warn about -mcpu= without an argument.
- if (A->getOption().matches(options::OPT_mcpu_EQ) &&
- A->containsValue("")) {
- Diag(clang::diag::warn_drv_empty_joined_argument) <<
- A->getAsString(*Args);
+ if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {
+ Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
}
}
- for (arg_iterator it = Args->filtered_begin(options::OPT_UNKNOWN),
- ie = Args->filtered_end(); it != ie; ++it) {
- Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
- }
+ for (const Arg *A : Args.filtered(options::OPT_UNKNOWN))
+ Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
return Args;
}
@@ -152,14 +146,13 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
// Determine which compilation mode we are in. We look for options which
// affect the phase, starting with the earliest phases, and record which
// option we used to determine the final phase.
-phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg)
-const {
+phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
+ Arg **FinalPhaseArg) const {
Arg *PhaseArg = nullptr;
phases::ID FinalPhase;
// -{E,EP,P,M,MM} only run the preprocessor.
- if (CCCIsCPP() ||
- (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
+ if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
(PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
@@ -181,8 +174,10 @@ const {
} 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.
@@ -195,7 +190,7 @@ const {
return FinalPhase;
}
-static Arg* MakeInputArg(DerivedArgList &Args, OptTable *Opts,
+static Arg *MakeInputArg(DerivedArgList &Args, OptTable *Opts,
StringRef Value) {
Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value,
Args.getBaseArgs().MakeIndex(Value), Value.data());
@@ -222,10 +217,9 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle));
// Add the remaining values as Xlinker arguments.
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
- if (StringRef(A->getValue(i)) != "--no-demangle")
- DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker),
- A->getValue(i));
+ for (const StringRef Val : A->getValues())
+ if (Val != "--no-demangle")
+ DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), Val);
continue;
}
@@ -253,15 +247,13 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// Rewrite unless -nostdlib is present.
if (!HasNostdlib && Value == "stdc++") {
- DAL->AddFlagArg(A, Opts->getOption(
- options::OPT_Z_reserved_lib_stdcxx));
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx));
continue;
}
// Rewrite unconditionally.
if (Value == "cc_kext") {
- DAL->AddFlagArg(A, Opts->getOption(
- options::OPT_Z_reserved_lib_cckext));
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_cckext));
continue;
}
}
@@ -269,18 +261,19 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// Pick up inputs via the -- option.
if (A->getOption().matches(options::OPT__DASH_DASH)) {
A->claim();
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
- DAL->append(MakeInputArg(*DAL, Opts, A->getValue(i)));
+ for (const StringRef Val : A->getValues())
+ DAL->append(MakeInputArg(*DAL, Opts, Val));
continue;
}
DAL->append(A);
}
- // Add a default value of -mlinker-version=, if one was given and the user
- // didn't specify one.
+// Add a default value of -mlinker-version=, if one was given and the user
+// didn't specify one.
#if defined(HOST_LINK_VERSION)
- if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+ if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&
+ strlen(HOST_LINK_VERSION) > 0) {
DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
HOST_LINK_VERSION);
DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
@@ -290,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");
@@ -299,8 +369,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (char *env = ::getenv("COMPILER_PATH")) {
StringRef CompilerPath = env;
while (!CompilerPath.empty()) {
- std::pair<StringRef, StringRef> Split
- = CompilerPath.split(llvm::sys::EnvPathSeparator);
+ std::pair<StringRef, StringRef> Split =
+ CompilerPath.split(llvm::sys::EnvPathSeparator);
PrefixDirs.push_back(Split.first);
CompilerPath = Split.second;
}
@@ -313,15 +383,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: What are we going to do with -V and -b?
// FIXME: This stuff needs to go into the Compilation, not the driver.
- bool CCCPrintActions;
+ bool CCCPrintPhases;
- InputArgList *Args = ParseArgStrings(ArgList.slice(1));
+ InputArgList Args = ParseArgStrings(ArgList.slice(1));
// -no-canonical-prefixes is used very early in main.
- Args->ClaimAllArgs(options::OPT_no_canonical_prefixes);
+ Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
// Ignore -pipe.
- Args->ClaimAllArgs(options::OPT_pipe);
+ Args.ClaimAllArgs(options::OPT_pipe);
// Extract -ccc args.
//
@@ -329,12 +399,12 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// should be outside in the client; the parts that aren't should have proper
// options, either by introducing new ones or by overloading gcc ones like -V
// or -b.
- CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases);
- CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings);
- if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name))
+ CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
+ CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
CCCGenericGCCName = A->getValue();
- CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch,
- options::OPT_ccc_pch_is_pth);
+ CCCUsePCH =
+ Args.hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth);
// FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
@@ -344,34 +414,43 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
T.setEnvironment(llvm::Triple::MSVC);
DefaultTargetTriple = T.str();
}
- if (const Arg *A = Args->getLastArg(options::OPT_target))
+ if (const Arg *A = Args.getLastArg(options::OPT_target))
DefaultTargetTriple = A->getValue();
- if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Dir = InstalledDir = A->getValue();
- for (arg_iterator it = Args->filtered_begin(options::OPT_B),
- ie = Args->filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A : Args.filtered(options::OPT_B)) {
A->claim();
PrefixDirs.push_back(A->getValue(0));
}
- if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ))
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
SysRoot = A->getValue();
- if (const Arg *A = Args->getLastArg(options::OPT__dyld_prefix_EQ))
+ if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
DyldPrefix = A->getValue();
- if (Args->hasArg(options::OPT_nostdlib))
+ if (Args.hasArg(options::OPT_nostdlib))
UseStdLib = false;
- if (const Arg *A = Args->getLastArg(options::OPT_resource_dir))
+ if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
ResourceDir = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {
+ SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
+ .Case("cwd", SaveTempsCwd)
+ .Case("obj", SaveTempsObj)
+ .Default(SaveTempsCwd);
+ }
+
+ std::unique_ptr<llvm::opt::InputArgList> UArgs =
+ llvm::make_unique<InputArgList>(std::move(Args));
+
// Perform the default argument translations.
- DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
+ DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
// Owned by the host.
- const ToolChain &TC = getToolChain(*Args);
+ const ToolChain &TC =
+ getToolChain(*UArgs, computeTargetTriple(DefaultTargetTriple, *UArgs));
// The compilation takes ownership of Args.
- Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs);
+ Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs);
if (!HandleImmediateArgs(*C))
return C;
@@ -383,13 +462,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Construct the list of abstract actions to perform for this compilation. On
// MachO targets this uses the driver-driver and universal actions.
if (TC.getTriple().isOSBinFormatMachO())
- BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
- Inputs, C->getActions());
+ BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(), Inputs,
+ C->getActions());
else
BuildActions(C->getDefaultToolChain(), C->getArgs(), Inputs,
C->getActions());
- if (CCCPrintActions) {
+ if (CCCPrintPhases) {
PrintActions(*C);
return C;
}
@@ -399,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.
@@ -416,8 +508,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
PrintVersion(C, llvm::errs());
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "PLEASE submit a bug report to " BUG_REPORT_URL " and include the "
- "crash backtrace, preprocessed source, and associated run script.";
+ << "PLEASE submit a bug report to " BUG_REPORT_URL " and include the "
+ "crash backtrace, preprocessed source, and associated run script.";
// Suppress driver output and emit preprocessor output to temp file.
Mode = CPPMode;
@@ -442,12 +534,12 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Ignore input from stdin or any inputs that cannot be preprocessed.
// Check type first as not all linker inputs have a value.
- if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
+ if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
IgnoreInput = true;
} else if (!strcmp(it->second->getValue(), "-")) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s) - ignoring input from stdin"
- ".";
+ << "Error generating preprocessed source(s) - "
+ "ignoring input from stdin.";
IgnoreInput = true;
}
@@ -461,7 +553,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
if (Inputs.empty()) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s) - no preprocessable inputs.";
+ << "Error generating preprocessed source(s) - "
+ "no preprocessable inputs.";
return;
}
@@ -476,8 +569,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
}
if (ArchNames.size() > 1) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s) - cannot generate "
- "preprocessed source with multiple -arch options.";
+ << "Error generating preprocessed source(s) - cannot generate "
+ "preprocessed source with multiple -arch options.";
return;
}
@@ -494,28 +587,28 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// If there were errors building the compilation, quit now.
if (Trap.hasErrorOccurred()) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s).";
+ << "Error generating preprocessed source(s).";
return;
}
// Generate preprocessed output.
SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
- C.ExecuteJob(C.getJobs(), FailingCommands);
+ C.ExecuteJobs(C.getJobs(), FailingCommands);
// If any of the preprocessing commands failed, clean up and exit.
if (!FailingCommands.empty()) {
- if (!C.getArgs().hasArg(options::OPT_save_temps))
+ if (!isSaveTempsEnabled())
C.CleanupFileList(C.getTempFiles(), true);
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s).";
+ << "Error generating preprocessed source(s).";
return;
}
const ArgStringList &TempFiles = C.getTempFiles();
if (TempFiles.empty()) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "Error generating preprocessed source(s).";
+ << "Error generating preprocessed source(s).";
return;
}
@@ -545,6 +638,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating run script: " + Script + " " + EC.message();
} else {
+ ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
+ << "# 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;
}
@@ -557,31 +655,22 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
<< "\n\n********************";
}
-void Driver::setUpResponseFiles(Compilation &C, Job &J) {
- if (JobList *Jobs = dyn_cast<JobList>(&J)) {
- for (auto &Job : *Jobs)
- setUpResponseFiles(C, Job);
- return;
- }
-
- Command *CurCommand = dyn_cast<Command>(&J);
- if (!CurCommand)
- return;
-
+void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
// Since argumentsFitWithinSystemLimits() may underestimate system's capacity
// if the tool does not support response files, there is a chance/ that things
// will just work without a response file, so we silently just skip it.
- if (CurCommand->getCreator().getResponseFilesSupport() == Tool::RF_None ||
- llvm::sys::argumentsFitWithinSystemLimits(CurCommand->getArguments()))
+ if (Cmd.getCreator().getResponseFilesSupport() == Tool::RF_None ||
+ llvm::sys::argumentsFitWithinSystemLimits(Cmd.getArguments()))
return;
std::string TmpName = GetTemporaryPath("response", "txt");
- CurCommand->setResponseFile(C.addTempFile(C.getArgs().MakeArgString(
- TmpName.c_str())));
+ Cmd.setResponseFile(
+ C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())));
}
-int Driver::ExecuteCompilation(Compilation &C,
- SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) {
+int Driver::ExecuteCompilation(
+ Compilation &C,
+ SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
C.getJobs().Print(llvm::errs(), "\n", true);
@@ -593,9 +682,10 @@ int Driver::ExecuteCompilation(Compilation &C,
return 1;
// Set up response file names for each command, if necessary
- setUpResponseFiles(C, C.getJobs());
+ for (auto &Job : C.getJobs())
+ setUpResponseFiles(C, Job);
- C.ExecuteJob(C.getJobs(), FailingCommands);
+ C.ExecuteJobs(C.getJobs(), FailingCommands);
// Remove temp files.
C.CleanupFileList(C.getTempFiles());
@@ -606,13 +696,12 @@ int Driver::ExecuteCompilation(Compilation &C,
// Otherwise, remove result files and print extra information about abnormal
// failures.
- for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it =
- FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) {
- int Res = it->first;
- const Command *FailingCommand = it->second;
+ for (const auto &CmdPair : FailingCommands) {
+ int Res = CmdPair.first;
+ const Command *FailingCommand = CmdPair.second;
// Remove result files if we're not saving temps.
- if (!C.getArgs().hasArg(options::OPT_save_temps)) {
+ if (!isSaveTempsEnabled()) {
const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());
C.CleanupFileMap(C.getResultFiles(), JA, true);
@@ -634,10 +723,10 @@ int Driver::ExecuteCompilation(Compilation &C,
// FIXME: See FIXME above regarding result code interpretation.
if (Res < 0)
Diag(clang::diag::err_drv_command_signalled)
- << FailingTool.getShortName();
+ << FailingTool.getShortName();
else
- Diag(clang::diag::err_drv_command_failed)
- << FailingTool.getShortName() << Res;
+ Diag(clang::diag::err_drv_command_failed) << FailingTool.getShortName()
+ << Res;
}
}
return 0;
@@ -647,7 +736,7 @@ void Driver::PrintHelp(bool ShowHidden) const {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks();
ExcludedFlagsBitmask |= options::NoDriverOption;
if (!ShowHidden)
@@ -678,8 +767,8 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
/// option.
static void PrintDiagnosticCategories(raw_ostream &OS) {
// Skip the empty category.
- for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories();
- i != max; ++i)
+ for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max;
+ ++i)
OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
}
@@ -733,25 +822,26 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
llvm::outs() << "programs: =";
- for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(),
- ie = TC.getProgramPaths().end(); it != ie; ++it) {
- if (it != TC.getProgramPaths().begin())
+ bool separator = false;
+ for (const std::string &Path : TC.getProgramPaths()) {
+ if (separator)
llvm::outs() << ':';
- llvm::outs() << *it;
+ llvm::outs() << Path;
+ separator = true;
}
llvm::outs() << "\n";
llvm::outs() << "libraries: =" << ResourceDir;
StringRef sysroot = C.getSysRoot();
- for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
- ie = TC.getFilePaths().end(); it != ie; ++it) {
+ for (const std::string &Path : TC.getFilePaths()) {
+ // Always print a separator. ResourceDir was the first item shown.
llvm::outs() << ':';
- const char *path = it->c_str();
- if (path[0] == '=')
- llvm::outs() << sysroot << path + 1;
+ // Interpretation of leading '=' is needed only for NetBSD.
+ if (Path[0] == '=')
+ llvm::outs() << sysroot << Path.substr(1);
else
- llvm::outs() << path;
+ llvm::outs() << Path;
}
llvm::outs() << "\n";
return false;
@@ -775,43 +865,32 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
- const MultilibSet &Multilibs = TC.getMultilibs();
-
- for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
- I != E; ++I) {
- llvm::outs() << *I << "\n";
- }
+ for (const Multilib &Multilib : TC.getMultilibs())
+ llvm::outs() << Multilib << "\n";
return false;
}
if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
- const MultilibSet &Multilibs = TC.getMultilibs();
- for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
- I != E; ++I) {
- if (I->gccSuffix().empty())
+ for (const Multilib &Multilib : TC.getMultilibs()) {
+ if (Multilib.gccSuffix().empty())
llvm::outs() << ".\n";
else {
- StringRef Suffix(I->gccSuffix());
+ StringRef Suffix(Multilib.gccSuffix());
assert(Suffix.front() == '/');
llvm::outs() << Suffix.substr(1) << "\n";
}
}
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;
}
+// Display an action graph human-readably. Action A is the "sink" node
+// and latest-occuring action. Traversal is in pre-order, visiting the
+// inputs to each action before printing the action itself.
static unsigned PrintActions1(const Compilation &C, Action *A,
- std::map<Action*, unsigned> &Ids) {
- if (Ids.count(A))
+ std::map<Action *, unsigned> &Ids) {
+ if (Ids.count(A)) // A was already visited.
return Ids[A];
std::string str;
@@ -821,15 +900,24 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
if (InputAction *IA = dyn_cast<InputAction>(A)) {
os << "\"" << IA->getInputArg().getValue() << "\"";
} else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
- os << '"' << BIA->getArchName() << '"'
- << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
+ 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 {
- os << "{";
- for (Action::iterator it = A->begin(), ie = A->end(); it != ie;) {
- os << PrintActions1(C, *it, Ids);
- ++it;
- if (it != ie)
- os << ", ";
+ 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 : *AL) {
+ os << Prefix << PrintActions1(C, PreRequisite, Ids);
+ Prefix = ", ";
}
os << "}";
}
@@ -842,18 +930,18 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
return Id;
}
+// Print the action graphs in a compilation C.
+// For example "clang -c file1.c file2.c" is composed of two subgraphs.
void Driver::PrintActions(const Compilation &C) const {
- std::map<Action*, unsigned> Ids;
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it)
- PrintActions1(C, *it, Ids);
+ std::map<Action *, unsigned> Ids;
+ for (Action *A : C.getActions())
+ PrintActions1(C, A, Ids);
}
/// \brief Check whether the given input tree contains any compilation or
/// assembly actions.
static bool ContainsCompileOrAssembleAction(const Action *A) {
- if (isa<CompileJobAction>(A) ||
- isa<BackendJobAction>(A) ||
+ if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) ||
isa<AssembleJobAction>(A))
return true;
@@ -864,8 +952,7 @@ static bool ContainsCompileOrAssembleAction(const Action *A) {
return false;
}
-void Driver::BuildUniversalActions(const ToolChain &TC,
- DerivedArgList &Args,
+void Driver::BuildUniversalActions(const ToolChain &TC, DerivedArgList &Args,
const InputList &BAInputs,
ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
@@ -878,10 +965,9 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// Validate the option here; we don't save the type here because its
// particular spelling may participate in other driver choices.
llvm::Triple::ArchType Arch =
- tools::darwin::getArchTypeForMachOArchName(A->getValue());
+ tools::darwin::getArchTypeForMachOArchName(A->getValue());
if (Arch == llvm::Triple::UnknownArch) {
- Diag(clang::diag::err_drv_invalid_arch_name)
- << A->getAsString(Args);
+ Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
continue;
}
@@ -912,7 +998,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
- << types::getTypeName(Act->getType());
+ << types::getTypeName(Act->getType());
ActionList Inputs;
for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
@@ -970,7 +1056,7 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
SmallString<64> Path(Value);
if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) {
- if (!llvm::sys::path::is_absolute(Path.str())) {
+ if (!llvm::sys::path::is_absolute(Path)) {
SmallString<64> Directory(WorkDir->getValue());
llvm::sys::path::append(Directory, Value);
Path.assign(Directory);
@@ -980,10 +1066,11 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
if (llvm::sys::fs::exists(Twine(Path)))
return true;
- if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value))
+ if (D.IsCLMode() && !llvm::sys::path::is_absolute(Twine(Path)) &&
+ llvm::sys::Process::FindInEnvPath("LIB", Value))
return true;
- D.Diag(clang::diag::err_drv_no_such_file) << Path.str();
+ D.Diag(clang::diag::err_drv_no_such_file) << Path;
return false;
}
@@ -1001,10 +1088,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
options::OPT__SLASH_TP)) {
InputTypeArg = TCTP;
InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
- ? types::TY_C : types::TY_CXX;
+ ? types::TY_C
+ : types::TY_CXX;
- arg_iterator it = Args.filtered_begin(options::OPT__SLASH_TC,
- options::OPT__SLASH_TP);
+ arg_iterator it =
+ Args.filtered_begin(options::OPT__SLASH_TC, options::OPT__SLASH_TP);
const arg_iterator ie = Args.filtered_end();
Arg *Previous = *it++;
bool ShowNote = false;
@@ -1066,7 +1154,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (Ty != OldTy)
Diag(clang::diag::warn_drv_treating_input_as_cxx)
- << getTypeName(OldTy) << getTypeName(Ty);
+ << getTypeName(OldTy) << getTypeName(Ty);
}
}
@@ -1140,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");
@@ -1168,7 +1343,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
!llvm::sys::path::is_separator(V.back())) {
// Check whether /Fo tries to name an output file for multiple inputs.
Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
- << A->getSpelling() << V;
+ << A->getSpelling() << V;
Args.eraseArg(options::OPT__SLASH_Fo);
}
}
@@ -1180,7 +1355,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
!llvm::sys::path::is_separator(V.back())) {
// Check whether /Fa tries to name an asm file for multiple inputs.
Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
- << A->getSpelling() << V;
+ << A->getSpelling() << V;
Args.eraseArg(options::OPT__SLASH_Fa);
}
}
@@ -1220,30 +1395,46 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// by a command-line argument with a corresponding Arg.
if (CCCIsCPP())
Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
- << InputArg->getAsString(Args)
- << getPhaseName(InitialPhase);
+ << InputArg->getAsString(Args) << getPhaseName(InitialPhase);
// Special case '-E' warning on a previously preprocessed file to make
// more sense.
else if (InitialPhase == phases::Compile &&
FinalPhase == phases::Preprocess &&
getPreprocessedType(InputType) == types::TY_INVALID)
Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
- << InputArg->getAsString(Args)
- << !!FinalPhaseArg
- << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+ << InputArg->getAsString(Args) << !!FinalPhaseArg
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
else
Diag(clang::diag::warn_drv_input_file_unused)
- << InputArg->getAsString(Args)
- << getPhaseName(InitialPhase)
- << !!FinalPhaseArg
- << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+ << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
+ << !!FinalPhaseArg
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
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(); i != e; ++i) {
+ for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
+ i != e; ++i) {
phases::ID Phase = *i;
// We are done if this step is past what the user requested.
@@ -1264,7 +1455,16 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
// Otherwise construct the appropriate action.
- Current = ConstructPhaseAction(Args, Phase, std::move(Current));
+ 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;
}
@@ -1290,12 +1490,14 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
}
std::unique_ptr<Action>
-Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
+ phases::ID Phase,
std::unique_ptr<Action> Input) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Build the appropriate action.
switch (Phase) {
- case phases::Link: llvm_unreachable("link action invalid here.");
+ case phases::Link:
+ llvm_unreachable("link action invalid here.");
case phases::Preprocess: {
types::ID OutputTy;
// -{M, MM} alter the output type.
@@ -1351,12 +1553,12 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
case phases::Backend: {
if (IsUsingLTO(Args)) {
types::ID Output =
- Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
+ Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
}
if (Args.hasArg(options::OPT_emit_llvm)) {
types::ID Output =
- Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
+ Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
}
return llvm::make_unique<BackendJobAction>(std::move(Input),
@@ -1371,10 +1573,7 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
}
bool Driver::IsUsingLTO(const ArgList &Args) const {
- if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false))
- return true;
-
- return false;
+ return Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false);
}
void Driver::BuildJobs(Compilation &C) const {
@@ -1420,11 +1619,10 @@ void Driver::BuildJobs(Compilation &C) const {
InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
- /*BoundArch*/nullptr,
+ /*BoundArch*/ nullptr,
/*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1,
- /*LinkingOutput*/ LinkingOutput,
- II);
+ /*LinkingOutput*/ LinkingOutput, II);
}
// If the user passed -Qunused-arguments or there were errors, don't warn
@@ -1434,10 +1632,10 @@ void Driver::BuildJobs(Compilation &C) const {
return;
// Claim -### here.
- (void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
+ (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
// Claim --driver-mode, it was handled earlier.
- (void) C.getArgs().hasArg(options::OPT_driver_mode);
+ (void)C.getArgs().hasArg(options::OPT_driver_mode);
for (Arg *A : C.getArgs()) {
// FIXME: It would be nice to be able to send the argument to the
@@ -1453,9 +1651,8 @@ void Driver::BuildJobs(Compilation &C) const {
if (Opt.getKind() == Option::FlagClass) {
bool DuplicateClaimed = false;
- for (arg_iterator it = C.getArgs().filtered_begin(&Opt),
- ie = C.getArgs().filtered_end(); it != ie; ++it) {
- if ((*it)->isClaimed()) {
+ for (const Arg *AA : C.getArgs().filtered(&Opt)) {
+ if (AA->isClaimed()) {
DuplicateClaimed = true;
break;
}
@@ -1466,13 +1663,13 @@ void Driver::BuildJobs(Compilation &C) const {
}
Diag(clang::diag::warn_drv_unused_argument)
- << A->getAsString(C.getArgs());
+ << A->getAsString(C.getArgs());
}
}
}
-static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
- const JobAction *JA,
+static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
+ const ToolChain *TC, const JobAction *JA,
const ActionList *&Inputs) {
const Tool *ToolForJob = nullptr;
@@ -1480,13 +1677,12 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
// bottom up, so what we are actually looking for is an assembler job with a
// compiler input.
- if (TC->useIntegratedAs() &&
- !C.getArgs().hasArg(options::OPT_save_temps) &&
+ if (TC->useIntegratedAs() && !SaveTemps &&
!C.getArgs().hasArg(options::OPT_via_file_asm) &&
!C.getArgs().hasArg(options::OPT__SLASH_FA) &&
!C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
- isa<AssembleJobAction>(JA) &&
- Inputs->size() == 1 && isa<BackendJobAction>(*Inputs->begin())) {
+ isa<AssembleJobAction>(JA) && Inputs->size() == 1 &&
+ isa<BackendJobAction>(*Inputs->begin())) {
// A BackendJob is always preceded by a CompileJob, and without
// -save-temps they will always get combined together, so instead of
// checking the backend tool, check if the tool for the CompileJob
@@ -1508,12 +1704,17 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
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;
- if (!Compiler->canEmitIR() ||
- !C.getArgs().hasArg(options::OPT_save_temps)) {
+ if (!Compiler->canEmitIR() || !SaveTemps) {
Inputs = &(*Inputs)[0]->getInputs();
ToolForJob = Compiler;
}
@@ -1528,8 +1729,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
// (irrelevant since we don't support combine yet).
if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) &&
!C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
- !C.getArgs().hasArg(options::OPT_traditional_cpp) &&
- !C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&
!C.getArgs().hasArg(options::OPT_rewrite_objc) &&
ToolForJob->hasIntegratedCPP())
Inputs = &(*Inputs)[0]->getInputs();
@@ -1537,16 +1737,27 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
return ToolForJob;
}
-void Driver::BuildJobsForAction(Compilation &C,
- const Action *A,
- const ToolChain *TC,
- const char *BoundArch,
- bool AtTopLevel,
- bool MultipleArchs,
+void Driver::BuildJobsForAction(Compilation &C, const Action *A,
+ const ToolChain *TC, const char *BoundArch,
+ bool AtTopLevel, bool MultipleArchs,
const char *LinkingOutput,
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?
@@ -1555,8 +1766,9 @@ void Driver::BuildJobsForAction(Compilation &C,
if (Input.getOption().matches(options::OPT_INPUT)) {
const char *Name = Input.getValue();
Result = InputInfo(Name, A->getType(), Name);
- } else
+ } else {
Result = InputInfo(&Input, A->getType(), "");
+ }
return;
}
@@ -1565,19 +1777,34 @@ void Driver::BuildJobsForAction(Compilation &C,
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, MultipleArchs, LinkingOutput, Result);
+ 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);
- const Tool *T = SelectToolForJob(C, TC, JA, Inputs);
+ const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs);
if (!T)
return;
@@ -1605,6 +1832,10 @@ void Driver::BuildJobsForAction(Compilation &C,
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);
@@ -1638,7 +1869,8 @@ const char *Driver::getDefaultImageName() const {
/// does not provide a filename, then use BaseName, and use the extension
/// suitable for FileType.
static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
- StringRef BaseName, types::ID FileType) {
+ StringRef BaseName,
+ types::ID FileType) {
SmallString<128> Filename = ArgValue;
if (ArgValue.empty()) {
@@ -1665,16 +1897,13 @@ static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
return Args.MakeArgString(Filename.c_str());
}
-const char *Driver::GetNamedOutputPath(Compilation &C,
- const JobAction &JA,
+const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
const char *BaseInput,
- const char *BoundArch,
- bool AtTopLevel,
+ const char *BoundArch, bool AtTopLevel,
bool MultipleArchs) const {
llvm::PrettyStackTraceString CrashInfo("Computing output path");
// Output to a user requested destination?
- if (AtTopLevel && !isa<DsymutilJobAction>(JA) &&
- !isa<VerifyJobAction>(JA)) {
+ if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
return C.addResultFile(FinalOutput->getValue(), &JA);
}
@@ -1684,11 +1913,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
assert(AtTopLevel && isa<PreprocessJobAction>(JA));
StringRef BaseName = llvm::sys::path::filename(BaseInput);
StringRef NameArg;
- if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi,
- options::OPT__SLASH_o))
+ if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
NameArg = A->getValue();
- return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName,
- types::TY_PP_C), &JA);
+ return C.addResultFile(
+ MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C),
+ &JA);
}
// Default to writing to stdout?
@@ -1703,19 +1932,19 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
// Use /Fa and the input filename to determine the asm file name.
StringRef BaseName = llvm::sys::path::filename(BaseInput);
StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
- return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName,
- JA.getType()), &JA);
+ return C.addResultFile(
+ MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, JA.getType()),
+ &JA);
}
// Output to a temporary file?
- if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
- !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
+ if ((!AtTopLevel && !isSaveTempsEnabled() &&
+ !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
CCGenDiagnostics) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
- std::string TmpName =
- GetTemporaryPath(Split.first,
- types::getTypeTempSuffix(JA.getType(), IsCLMode()));
+ std::string TmpName = GetTemporaryPath(
+ Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
@@ -1734,22 +1963,27 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
if (JA.getType() == types::TY_Object &&
C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
// The /Fo or /o flag decides the object filename.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo,
- options::OPT__SLASH_o)->getValue();
- NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
- types::TY_Object);
+ StringRef Val =
+ C.getArgs()
+ .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)
+ ->getValue();
+ NamedOutput =
+ MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);
} else if (JA.getType() == types::TY_Image &&
- C.getArgs().hasArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)) {
+ C.getArgs().hasArg(options::OPT__SLASH_Fe,
+ options::OPT__SLASH_o)) {
// The /Fe or /o flag names the linked file.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe,
- options::OPT__SLASH_o)->getValue();
- NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
- types::TY_Image);
+ StringRef Val =
+ C.getArgs()
+ .getLastArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)
+ ->getValue();
+ NamedOutput =
+ MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image);
} else if (JA.getType() == types::TY_Image) {
if (IsCLMode()) {
// clang-cl uses BaseName for the executable name.
- NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
- types::TY_Image);
+ NamedOutput =
+ MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);
} else if (MultipleArchs && BoundArch) {
SmallString<128> Output(getDefaultImageName());
Output += "-";
@@ -1780,11 +2014,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
}
+ // Prepend object file path if -save-temps=obj
+ if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) &&
+ JA.getType() != types::TY_PCH) {
+ Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+ SmallString<128> TempPath(FinalOutput->getValue());
+ llvm::sys::path::remove_filename(TempPath);
+ StringRef OutputFileName = llvm::sys::path::filename(NamedOutput);
+ llvm::sys::path::append(TempPath, OutputFileName);
+ NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());
+ }
+
// If we're saving temps and the temp file conflicts with the input file,
// then avoid overwriting input file.
- if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) &&
- NamedOutput == BaseName) {
-
+ if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {
bool SameFile = false;
SmallString<256> Result;
llvm::sys::fs::current_path(Result);
@@ -1794,9 +2037,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
if (SameFile) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
- std::string TmpName =
- GetTemporaryPath(Split.first,
- types::getTypeTempSuffix(JA.getType(), IsCLMode()));
+ std::string TmpName = GetTemporaryPath(
+ Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
}
@@ -1817,14 +2059,10 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
// Respect a limited subset of the '-Bprefix' functionality in GCC by
// attempting to use this prefix when looking for file paths.
- for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
- ie = PrefixDirs.end(); it != ie; ++it) {
- std::string Dir(*it);
+ for (const std::string &Dir : PrefixDirs) {
if (Dir.empty())
continue;
- if (Dir[0] == '=')
- Dir = SysRoot + Dir.substr(1);
- SmallString<128> P(Dir);
+ SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
llvm::sys::path::append(P, Name);
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
@@ -1835,15 +2073,10 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
- const ToolChain::path_list &List = TC.getFilePaths();
- for (ToolChain::path_list::const_iterator
- it = List.begin(), ie = List.end(); it != ie; ++it) {
- std::string Dir(*it);
+ for (const std::string &Dir : TC.getFilePaths()) {
if (Dir.empty())
continue;
- if (Dir[0] == '=')
- Dir = SysRoot + Dir.substr(1);
- SmallString<128> P(Dir);
+ SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
llvm::sys::path::append(P, Name);
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
@@ -1852,12 +2085,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
return Name;
}
-void
-Driver::generatePrefixedToolNames(const char *Tool, const ToolChain &TC,
- SmallVectorImpl<std::string> &Names) const {
+void Driver::generatePrefixedToolNames(
+ const char *Tool, const ToolChain &TC,
+ SmallVectorImpl<std::string> &Names) const {
// FIXME: Needs a better variable than DefaultTargetTriple
- Names.push_back(DefaultTargetTriple + "-" + Tool);
- Names.push_back(Tool);
+ Names.emplace_back(DefaultTargetTriple + "-" + Tool);
+ Names.emplace_back(Tool);
}
static bool ScanDirForExecutable(SmallString<128> &Dir,
@@ -1906,8 +2139,8 @@ std::string Driver::GetProgramPath(const char *Name,
return Name;
}
-std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
- const {
+std::string Driver::GetTemporaryPath(StringRef Prefix,
+ const char *Suffix) const {
SmallString<128> Path;
std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
if (EC) {
@@ -1918,97 +2151,15 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
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) {
switch (Target.getOS()) {
+ case llvm::Triple::CloudABI:
+ TC = new toolchains::CloudABI(*this, Target, Args);
+ break;
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
@@ -2038,6 +2189,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
else
TC = new toolchains::Linux(*this, Target, Args);
break;
+ case llvm::Triple::NaCl:
+ TC = new toolchains::NaCl_TC(*this, Target, Args);
+ break;
case llvm::Triple::Solaris:
TC = new toolchains::Solaris(*this, Target, Args);
break;
@@ -2052,12 +2206,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
case llvm::Triple::GNU:
- // FIXME: We need a MinGW toolchain. Use the default Generic_GCC
- // toolchain for now as the default case would below otherwise.
- if (Target.isOSBinFormatELF())
- TC = new toolchains::Generic_ELF(*this, Target, Args);
- else
- TC = new toolchains::Generic_GCC(*this, Target, Args);
+ TC = new toolchains::MinGW(*this, Target, Args);
break;
case llvm::Triple::Itanium:
TC = new toolchains::CrossWindowsToolChain(*this, Target, Args);
@@ -2068,30 +2217,26 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
}
break;
+ case llvm::Triple::CUDA:
+ TC = new toolchains::CudaToolChain(*this, Target, Args);
+ break;
default:
- // TCE is an OSless target
- if (Target.getArchName() == "tce") {
+ // Of these targets, Hexagon is the only one that might have
+ // an OS of Linux, in which case it got handled above already.
+ if (Target.getArchName() == "tce")
TC = new toolchains::TCEToolChain(*this, Target, Args);
- break;
- }
- // If Hexagon is configured as an OSless target
- if (Target.getArch() == llvm::Triple::hexagon) {
+ else if (Target.getArch() == llvm::Triple::hexagon)
TC = new toolchains::Hexagon_TC(*this, Target, Args);
- break;
- }
- if (Target.getArch() == llvm::Triple::xcore) {
+ else if (Target.getArch() == llvm::Triple::xcore)
TC = new toolchains::XCore(*this, Target, Args);
- break;
- }
- if (Target.isOSBinFormatELF()) {
+ else if (Target.getArch() == llvm::Triple::shave)
+ TC = new toolchains::SHAVEToolChain(*this, Target, Args);
+ else if (Target.isOSBinFormatELF())
TC = new toolchains::Generic_ELF(*this, Target, Args);
- break;
- }
- if (Target.isOSBinFormatMachO()) {
+ else if (Target.isOSBinFormatMachO())
TC = new toolchains::MachO(*this, Target, Args);
- break;
- }
- TC = new toolchains::Generic_GCC(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
}
}
@@ -2099,13 +2244,11 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
}
bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
- // Check if user requested no clang, or clang doesn't understand this type (we
- // only handle single inputs for now).
- if (JA.size() != 1 ||
- !types::isAcceptedByClang((*JA.begin())->getType()))
+ // Say "no" if there is not exactly one input of a type clang understands.
+ if (JA.size() != 1 || !types::isAcceptedByClang((*JA.begin())->getType()))
return false;
- // Otherwise make sure this is an action clang understands.
+ // And say "no" if this is not a kind of action clang understands.
if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
!isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
return false;
@@ -2125,24 +2268,24 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
Major = Minor = Micro = 0;
if (*Str == '\0')
- return true;
+ return false;
char *End;
- Major = (unsigned) strtol(Str, &End, 10);
+ Major = (unsigned)strtol(Str, &End, 10);
if (*Str != '\0' && *End == '\0')
return true;
if (*End != '.')
return false;
- Str = End+1;
- Minor = (unsigned) strtol(Str, &End, 10);
+ Str = End + 1;
+ Minor = (unsigned)strtol(Str, &End, 10);
if (*Str != '\0' && *End == '\0')
return true;
if (*End != '.')
return false;
- Str = End+1;
- Micro = (unsigned) strtol(Str, &End, 10);
+ Str = End + 1;
+ Micro = (unsigned)strtol(Str, &End, 10);
if (*Str != '\0' && *End == '\0')
return true;
if (Str == End)
@@ -2166,6 +2309,6 @@ std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const {
return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
}
-bool clang::driver::isOptimizationLevelFast(const llvm::opt::ArgList &Args) {
+bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
index c5b3f5a..42bba56 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -25,16 +25,12 @@ using llvm::raw_ostream;
using llvm::StringRef;
using llvm::ArrayRef;
-Job::~Job() {}
+Command::Command(const Action &Source, const Tool &Creator,
+ const char *Executable, const ArgStringList &Arguments)
+ : Source(Source), Creator(Creator), Executable(Executable),
+ Arguments(Arguments), ResponseFile(nullptr) {}
-Command::Command(const Action &_Source, const Tool &_Creator,
- const char *_Executable,
- const ArgStringList &_Arguments)
- : Job(CommandClass), Source(_Source), Creator(_Creator),
- Executable(_Executable), Arguments(_Arguments),
- ResponseFile(nullptr) {}
-
-static int skipArgs(const char *Flag) {
+static int skipArgs(const char *Flag, bool HaveCrashVFS) {
// These flags are all of the form -Flag <Arg> and are treated as two
// arguments. Therefore, we need to skip the flag and the next argument.
bool Res = llvm::StringSwitch<bool>(Flag)
@@ -43,9 +39,11 @@ static int skipArgs(const char *Flag) {
.Cases("-fdebug-compilation-dir", "-idirafter", true)
.Cases("-include", "-include-pch", "-internal-isystem", true)
.Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
- .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
+ .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
.Cases("-resource-dir", "-serialize-diagnostic-file", true)
.Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
+ // Some include flags shouldn't be skipped if we have a crash VFS
+ .Case("-isysroot", !HaveCrashVFS)
.Default(false);
// Match found.
@@ -73,7 +71,7 @@ static int skipArgs(const char *Flag) {
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) {
@@ -148,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;
@@ -164,11 +162,12 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
if (StringRef(Args[I]).equals("-main-file-name"))
MainFilename = Args[I + 1];
+ bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty();
for (size_t i = 0, e = Args.size(); i < e; ++i) {
const char *const Arg = Args[i];
if (CrashInfo) {
- if (int Skip = skipArgs(Arg)) {
+ if (int Skip = skipArgs(Arg, HaveCrashVFS)) {
i += Skip - 1;
continue;
} else if (llvm::sys::path::filename(Arg) == MainFilename &&
@@ -176,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 && !CrashInfo->VFSPath.empty()) {
+ 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) {
@@ -217,8 +216,7 @@ int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
if (ResponseFile == nullptr) {
Argv.push_back(Executable);
- for (size_t i = 0, e = Arguments.size(); i != e; ++i)
- Argv.push_back(Arguments[i]);
+ Argv.append(Arguments.begin(), Arguments.end());
Argv.push_back(nullptr);
return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
@@ -293,8 +291,6 @@ int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
return SecondaryStatus;
}
-JobList::JobList() : Job(JobListClass) {}
-
void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
for (const auto &Job : *this)
diff --git a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
index d6bd5c3..c816b29 100644
--- a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ToolChains.h"
+#include "Tools.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Compilation.h"
@@ -21,6 +22,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h"
+#include <cstdio>
// Include the necessary headers to interface with the Windows registry and
// environment.
@@ -51,12 +53,12 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
}
Tool *MSVCToolChain::buildLinker() const {
- return new tools::visualstudio::Link(*this);
+ return new tools::visualstudio::Linker(*this);
}
Tool *MSVCToolChain::buildAssembler() const {
if (getTriple().isOSBinFormatMachO())
- return new tools::darwin::Assemble(*this);
+ return new tools::darwin::Assembler(*this);
getDriver().Diag(clang::diag::err_no_external_assembler);
return nullptr;
}
@@ -212,7 +214,7 @@ bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder", path, &sdkVersion);
if (!sdkVersion.empty())
- ::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
+ std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
return hasSDKDir && !path.empty();
}
@@ -423,7 +425,7 @@ void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
const char *subfolder) const {
llvm::SmallString<128> path(folder);
llvm::sys::path::append(path, subfolder);
- addSystemInclude(DriverArgs, CC1Args, path.str());
+ addSystemInclude(DriverArgs, CC1Args, path);
}
void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -434,7 +436,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(getDriver().ResourceDir);
llvm::sys::path::append(P, "include");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ addSystemInclude(DriverArgs, CC1Args, P);
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@@ -494,3 +496,35 @@ void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// FIXME: There should probably be logic here to find libc++ on Windows.
}
+
+std::string
+MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ std::string TripleStr =
+ ToolChain::ComputeEffectiveClangTriple(Args, InputType);
+ llvm::Triple Triple(TripleStr);
+ VersionTuple MSVT =
+ tools::visualstudio::getMSVCVersion(/*D=*/nullptr, Triple, Args,
+ /*IsWindowsMSVC=*/true);
+ if (MSVT.empty())
+ return TripleStr;
+
+ MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
+ MSVT.getSubminor().getValueOr(0));
+
+ if (Triple.getEnvironment() == llvm::Triple::MSVC) {
+ StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
+ if (ObjFmt.empty())
+ Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
+ else
+ Triple.setEnvironmentName(
+ (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
+ }
+ return Triple.getTriple();
+}
+
+SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/MinGWToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/MinGWToolChain.cpp
new file mode 100644
index 0000000..197c19e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/MinGWToolChain.cpp
@@ -0,0 +1,175 @@
+//===--- MinGWToolChain.cpp - MinGWToolChain Implementation ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ToolChains.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::diag;
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+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 =
+ llvm::sys::findProgramByName("gcc"))
+ Base = llvm::sys::path::parent_path(
+ llvm::sys::path::parent_path(GPPName.get()));
+ else
+ Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
+ Base += llvm::sys::path::get_separator();
+ 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.
+ Arch = getTriple().getArchName();
+ Arch += "-w64-mingw32";
+ std::error_code EC;
+ 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";
+ llvm::sys::fs::directory_iterator MingwOrgEntry(LibDir + Arch, EC);
+ if (!EC)
+ GccLibDir = MingwOrgEntry->path();
+ }
+ Arch += llvm::sys::path::get_separator();
+ // GccLibDir must precede Base/lib so that the
+ // correct crtbegin.o ,cetend.o would be found.
+ 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; }
+
+Tool *MinGW::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::PreprocessJobClass:
+ if (!Preprocessor)
+ Preprocessor.reset(new tools::gcc::Preprocessor(*this));
+ return Preprocessor.get();
+ case Action::CompileJobClass:
+ if (!Compiler)
+ Compiler.reset(new tools::gcc::Compiler(*this));
+ return Compiler.get();
+ default:
+ return ToolChain::getTool(AC);
+ }
+}
+
+Tool *MinGW::buildAssembler() const {
+ return new tools::MinGW::Assembler(*this);
+}
+
+Tool *MinGW::buildLinker() const { return new tools::MinGW::Linker(*this); }
+
+bool MinGW::IsUnwindTablesDefault() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+bool MinGW::isPICDefault() const { return getArch() == llvm::Triple::x86_64; }
+
+bool MinGW::isPIEDefault() const { return false; }
+
+bool MinGW::isPICDefaultForced() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+bool MinGW::UseSEHExceptions() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<1024> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ llvm::SmallString<1024> IncludeDir(GccLibDir);
+ 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");
+}
+
+void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // 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/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
index 1f5d62f..8acda67 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
@@ -151,41 +151,23 @@ MultilibSet &MultilibSet::Maybe(const Multilib &M) {
}
MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) {
- std::vector<Multilib> Ms;
- Ms.push_back(M1);
- Ms.push_back(M2);
- return Either(Ms);
+ return Either({M1, M2});
}
MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
const Multilib &M3) {
- std::vector<Multilib> Ms;
- Ms.push_back(M1);
- Ms.push_back(M2);
- Ms.push_back(M3);
- return Either(Ms);
+ return Either({M1, M2, M3});
}
MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
const Multilib &M3, const Multilib &M4) {
- std::vector<Multilib> Ms;
- Ms.push_back(M1);
- Ms.push_back(M2);
- Ms.push_back(M3);
- Ms.push_back(M4);
- return Either(Ms);
+ return Either({M1, M2, M3, M4});
}
MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
const Multilib &M3, const Multilib &M4,
const Multilib &M5) {
- std::vector<Multilib> Ms;
- Ms.push_back(M1);
- Ms.push_back(M2);
- Ms.push_back(M3);
- Ms.push_back(M4);
- Ms.push_back(M5);
- return Either(Ms);
+ return Either({M1, M2, M3, M4, M5});
}
static Multilib compose(const Multilib &Base, const Multilib &New) {
@@ -197,7 +179,7 @@ static Multilib compose(const Multilib &Base, const Multilib &New) {
llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
New.includeSuffix());
- Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str());
+ Multilib Composed(GCCSuffix, OSSuffix, IncludeSuffix);
Multilib::flags_list &Flags = Composed.flags();
@@ -207,8 +189,7 @@ static Multilib compose(const Multilib &Base, const Multilib &New) {
return Composed;
}
-MultilibSet &
-MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
+MultilibSet &MultilibSet::Either(ArrayRef<Multilib> MultilibSegments) {
multilib_list Composed;
if (Multilibs.empty())
@@ -229,30 +210,23 @@ MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
return *this;
}
-MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) {
+MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
filterInPlace(F, Multilibs);
return *this;
}
-MultilibSet &MultilibSet::FilterOut(std::string Regex) {
- class REFilter : public MultilibSet::FilterCallback {
- mutable llvm::Regex R;
-
- public:
- REFilter(std::string Regex) : R(Regex) {}
- bool operator()(const Multilib &M) const override {
- std::string Error;
- if (!R.isValid(Error)) {
- llvm::errs() << Error;
- assert(false);
- return false;
- }
- return R.match(M.gccSuffix());
- }
- };
+MultilibSet &MultilibSet::FilterOut(const char *Regex) {
+ llvm::Regex R(Regex);
+#ifndef NDEBUG
+ std::string Error;
+ if (!R.isValid(Error)) {
+ llvm::errs() << Error;
+ llvm_unreachable("Invalid regex!");
+ }
+#endif
- REFilter REF(Regex);
- filterInPlace(REF, Multilibs);
+ filterInPlace([&R](const Multilib &M) { return R.match(M.gccSuffix()); },
+ Multilibs);
return *this;
}
@@ -262,38 +236,29 @@ void MultilibSet::combineWith(const MultilibSet &Other) {
Multilibs.insert(Multilibs.end(), Other.begin(), Other.end());
}
+static bool isFlagEnabled(StringRef Flag) {
+ char Indicator = Flag.front();
+ assert(Indicator == '+' || Indicator == '-');
+ return Indicator == '+';
+}
+
bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
- class FilterFlagsMismatch : public MultilibSet::FilterCallback {
- llvm::StringMap<bool> FlagSet;
-
- public:
- FilterFlagsMismatch(const std::vector<std::string> &Flags) {
- // Stuff all of the flags into the FlagSet such that a true mappend
- // indicates the flag was enabled, and a false mappend indicates the
- // flag was disabled
- for (StringRef Flag : Flags)
- FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
- }
- bool operator()(const Multilib &M) const override {
- for (StringRef Flag : M.flags()) {
- llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
- if (SI != FlagSet.end())
- if (SI->getValue() != isFlagEnabled(Flag))
- return true;
- }
- return false;
- }
- private:
- bool isFlagEnabled(StringRef Flag) const {
- char Indicator = Flag.front();
- assert(Indicator == '+' || Indicator == '-');
- return Indicator == '+';
+ llvm::StringMap<bool> FlagSet;
+
+ // Stuff all of the flags into the FlagSet such that a true mappend indicates
+ // the flag was enabled, and a false mappend indicates the flag was disabled.
+ for (StringRef Flag : Flags)
+ FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
+
+ multilib_list Filtered = filterCopy([&FlagSet](const Multilib &M) {
+ for (StringRef Flag : M.flags()) {
+ llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
+ if (SI != FlagSet.end())
+ if (SI->getValue() != isFlagEnabled(Flag))
+ return true;
}
- };
-
- FilterFlagsMismatch FlagsMismatch(Flags);
-
- multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs);
+ return false;
+ }, Multilibs);
if (Filtered.size() == 0) {
return false;
@@ -313,19 +278,15 @@ void MultilibSet::print(raw_ostream &OS) const {
OS << M << "\n";
}
-MultilibSet::multilib_list
-MultilibSet::filterCopy(const MultilibSet::FilterCallback &F,
- const multilib_list &Ms) {
+MultilibSet::multilib_list MultilibSet::filterCopy(FilterCallback F,
+ const multilib_list &Ms) {
multilib_list Copy(Ms);
filterInPlace(F, Copy);
return Copy;
}
-void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F,
- multilib_list &Ms) {
- Ms.erase(std::remove_if(Ms.begin(), Ms.end(),
- [&F](const Multilib &M) { return F(M); }),
- Ms.end());
+void MultilibSet::filterInPlace(FilterCallback F, multilib_list &Ms) {
+ Ms.erase(std::remove_if(Ms.begin(), Ms.end(), F), Ms.end());
}
raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
index bd7bc21..c3ad8ef 100644
--- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/SanitizerArgs.h"
+#include "Tools.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
@@ -18,74 +20,45 @@
#include "llvm/Support/SpecialCaseList.h"
#include <memory>
+using namespace clang;
+using namespace clang::SanitizerKind;
using namespace clang::driver;
using namespace llvm::opt;
-namespace {
-/// Assign ordinals to possible values of -fsanitize= flag.
-/// We use the ordinal values as bit positions within \c SanitizeKind.
-enum SanitizeOrdinal {
-#define SANITIZER(NAME, ID) SO_##ID,
-#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
-#include "clang/Basic/Sanitizers.def"
- SO_Count
-};
-
-/// Represents a set of sanitizer kinds. It is also used to define:
-/// 1) set of sanitizers each sanitizer group expands into.
-/// 2) set of sanitizers sharing a specific property (e.g.
-/// all sanitizers with zero-base shadow).
-enum SanitizeKind {
-#define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
-#define SANITIZER_GROUP(NAME, ID, ALIAS) \
-ID = ALIAS, ID##Group = 1 << SO_##ID##Group,
-#include "clang/Basic/Sanitizers.def"
- NeedsUbsanRt = Undefined | Integer,
+enum : SanitizerMask {
+ NeedsUbsanRt = Undefined | Integer | CFI,
+ NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
RequiresPIE = Memory | DataFlow,
NeedsUnwindTables = Address | Thread | Memory | DataFlow,
- SupportsCoverage = Address | Memory | Leak | Undefined | Integer,
+ SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
RecoverableByDefault = Undefined | Integer,
Unrecoverable = Address | Unreachable | Return,
- LegacyFsanitizeRecoverMask = Undefined | Integer
+ LegacyFsanitizeRecoverMask = Undefined | Integer,
+ NeedsLTO = CFI,
+ TrappingSupported =
+ (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
+ TrappingDefault = CFI,
};
-}
-
-/// Returns true if set of \p Sanitizers contain at least one sanitizer from
-/// \p Kinds.
-static bool hasOneOf(const clang::SanitizerSet &Sanitizers, unsigned Kinds) {
-#define SANITIZER(NAME, ID) \
- if (Sanitizers.has(clang::SanitizerKind::ID) && (Kinds & ID)) \
- return true;
-#include "clang/Basic/Sanitizers.def"
- return false;
-}
-
-/// Adds all sanitizers from \p Kinds to \p Sanitizers.
-static void addAllOf(clang::SanitizerSet &Sanitizers, unsigned Kinds) {
-#define SANITIZER(NAME, ID) \
- if (Kinds & ID) \
- Sanitizers.set(clang::SanitizerKind::ID, true);
-#include "clang/Basic/Sanitizers.def"
-}
-
-static unsigned toSanitizeKind(clang::SanitizerKind K) {
-#define SANITIZER(NAME, ID) \
- if (K == clang::SanitizerKind::ID) \
- return ID;
-#include "clang/Basic/Sanitizers.def"
- llvm_unreachable("Invalid SanitizerKind!");
-}
-/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
-/// Returns a member of the \c SanitizeKind enumeration, or \c 0
-/// if \p Value is not known.
-static unsigned parseValue(const char *Value);
+enum CoverageFeature {
+ CoverageFunc = 1 << 0,
+ CoverageBB = 1 << 1,
+ CoverageEdge = 1 << 2,
+ CoverageIndirCall = 1 << 3,
+ CoverageTraceBB = 1 << 4,
+ CoverageTraceCmp = 1 << 5,
+ Coverage8bitCounters = 1 << 6,
+};
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
-/// invalid components. Returns OR of members of \c SanitizeKind enumeration.
-static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
- bool DiagnoseErrors);
+/// invalid components. Returns a SanitizerMask.
+static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors);
+
+/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
+/// components. Returns OR of members of \c CoverageFeature enumeration.
+static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides some sanitizer kind from \p Mask. For example, the argument list
@@ -93,68 +66,119 @@ static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
/// would produce "-fsanitize=vptr".
static std::string lastArgumentForMask(const Driver &D,
const llvm::opt::ArgList &Args,
- unsigned Mask);
-
-static std::string lastArgumentForKind(const Driver &D,
- const llvm::opt::ArgList &Args,
- clang::SanitizerKind K) {
- return lastArgumentForMask(D, Args, toSanitizeKind(K));
-}
+ SanitizerMask Mask);
/// Produce an argument string from argument \p A, which shows how it provides
/// a value in \p Mask. For instance, the argument
/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
/// "-fsanitize=alignment".
-static std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask);
+static std::string describeSanitizeArg(const llvm::opt::Arg *A,
+ SanitizerMask Mask);
/// Produce a string containing comma-separated names of sanitizers in \p
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);
-/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
-/// this group enables.
-static unsigned expandGroups(unsigned Kinds);
-
-static unsigned getToolchainUnsupportedKinds(const ToolChain &TC) {
- bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
- bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
- bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
- bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
+static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
+ std::string &BLPath) {
+ const char *BlacklistFile = nullptr;
+ if (Kinds & Address)
+ BlacklistFile = "asan_blacklist.txt";
+ else if (Kinds & Memory)
+ BlacklistFile = "msan_blacklist.txt";
+ else if (Kinds & Thread)
+ BlacklistFile = "tsan_blacklist.txt";
+ else if (Kinds & DataFlow)
+ BlacklistFile = "dfsan_abilist.txt";
- unsigned Unsupported = 0;
- if (!(IsLinux && IsX86_64)) {
- Unsupported |= Memory | DataFlow;
- }
- if (!((IsLinux || IsFreeBSD) && IsX86_64)) {
- Unsupported |= Thread;
+ if (BlacklistFile) {
+ clang::SmallString<64> Path(D.ResourceDir);
+ llvm::sys::path::append(Path, BlacklistFile);
+ BLPath = Path.str();
+ return true;
}
- if (!(IsLinux && (IsX86 || IsX86_64))) {
- Unsupported |= Function;
+ return false;
+}
+
+/// Sets group bits for every group that has at least one representative already
+/// enabled in \p Kinds.
+static SanitizerMask setGroupBits(SanitizerMask Kinds) {
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ if (Kinds & SanitizerKind::ID) \
+ Kinds |= SanitizerKind::ID##Group;
+#include "clang/Basic/Sanitizers.def"
+ return Kinds;
+}
+
+static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
+ const llvm::opt::ArgList &Args) {
+ SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
+ SanitizerMask TrappingKinds = 0;
+ SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
+
+ for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
+ I != E; ++I) {
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
+ Arg->claim();
+ SanitizerMask Add = parseArgValues(D, Arg, true);
+ Add &= ~TrapRemove;
+ if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
+ SanitizerSet S;
+ S.Mask = InvalidValues;
+ D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
+ << toString(S);
+ }
+ TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
+ Arg->claim();
+ TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
+ } else if (Arg->getOption().matches(
+ options::OPT_fsanitize_undefined_trap_on_error)) {
+ Arg->claim();
+ TrappingKinds |=
+ expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
+ } else if (Arg->getOption().matches(
+ options::OPT_fno_sanitize_undefined_trap_on_error)) {
+ Arg->claim();
+ TrapRemove |= expandSanitizerGroups(UndefinedGroup);
+ }
}
- return Unsupported;
+
+ // Apply default trapping behavior.
+ TrappingKinds |= TrappingDefault & ~TrapRemove;
+
+ return TrappingKinds;
}
bool SanitizerArgs::needsUbsanRt() const {
- return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
+ return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) &&
+ !Sanitizers.has(Address) &&
+ !Sanitizers.has(Memory) &&
+ !Sanitizers.has(Thread);
}
bool SanitizerArgs::requiresPIE() const {
- return AsanZeroBaseShadow || hasOneOf(Sanitizers, RequiresPIE);
+ return AsanZeroBaseShadow || (Sanitizers.Mask & RequiresPIE);
}
bool SanitizerArgs::needsUnwindTables() const {
- return hasOneOf(Sanitizers, NeedsUnwindTables);
+ return Sanitizers.Mask & NeedsUnwindTables;
}
void SanitizerArgs::clear() {
Sanitizers.clear();
RecoverableSanitizers.clear();
- BlacklistFile = "";
- SanitizeCoverage = 0;
+ TrapSanitizers.clear();
+ BlacklistFiles.clear();
+ CoverageFeatures = 0;
MsanTrackOrigins = 0;
+ MsanUseAfterDtor = false;
AsanFieldPadding = 0;
AsanZeroBaseShadow = false;
- UbsanTrapOnError = false;
AsanSharedRuntime = false;
LinkCXXRuntimes = false;
}
@@ -162,161 +186,227 @@ void SanitizerArgs::clear() {
SanitizerArgs::SanitizerArgs(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
clear();
- unsigned AllRemove = 0; // During the loop below, the accumulated set of
- // sanitizers disabled by the current sanitizer
- // argument or any argument after it.
- unsigned DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
- // Used to deduplicate diagnostics.
- unsigned Kinds = 0;
- unsigned NotSupported = getToolchainUnsupportedKinds(TC);
+ SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
+ SanitizerMask AllAddedKinds = 0; // Mask of all sanitizers ever enabled by
+ // -fsanitize= flags (directly or via group
+ // expansion), some of which may be disabled
+ // later. Used to carefully prune
+ // unused-argument diagnostics.
+ SanitizerMask DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
+ // Used to deduplicate diagnostics.
+ SanitizerMask Kinds = 0;
+ const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+
const Driver &D = TC.getDriver();
+ SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
+ SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
+
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
const auto *Arg = *I;
if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
Arg->claim();
- unsigned Add = parseArgValues(D, Arg, true);
+ SanitizerMask Add = parseArgValues(D, Arg, true);
+ AllAddedKinds |= expandSanitizerGroups(Add);
// Avoid diagnosing any sanitizer which is disabled later.
Add &= ~AllRemove;
// At this point we have not expanded groups, so any unsupported
// sanitizers in Add are those which have been explicitly enabled.
// Diagnose them.
- if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
- // Only diagnose the new kinds.
+ if (SanitizerMask KindsToDiagnose =
+ Add & InvalidTrappingKinds & ~DiagnosedKinds) {
+ std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << Desc << "-fsanitize-trap=undefined";
+ DiagnosedKinds |= KindsToDiagnose;
+ }
+ Add &= ~InvalidTrappingKinds;
+ if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Desc << TC.getTriple().str();
DiagnosedKinds |= KindsToDiagnose;
}
- Add &= ~NotSupported;
+ Add &= Supported;
+
+ // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
+ // so we don't error out if -fno-rtti and -fsanitize=undefined were
+ // passed.
+ if (Add & Vptr &&
+ (RTTIMode == ToolChain::RM_DisabledImplicitly ||
+ RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ if (RTTIMode == ToolChain::RM_DisabledImplicitly)
+ // Warn about not having rtti enabled if the vptr sanitizer is
+ // explicitly enabled
+ D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
+ else {
+ const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
+ assert(NoRTTIArg &&
+ "RTTI disabled explicitly but we have no argument!");
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
+ }
- Add = expandGroups(Add);
+ // Take out the Vptr sanitizer from the enabled sanitizers
+ AllRemove |= Vptr;
+ }
+
+ Add = expandSanitizerGroups(Add);
// Group expansion may have enabled a sanitizer which is disabled later.
Add &= ~AllRemove;
// Silently discard any unsupported sanitizers implicitly enabled through
// group expansion.
- Add &= ~NotSupported;
+ Add &= ~InvalidTrappingKinds;
+ Add &= Supported;
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
Arg->claim();
- unsigned Remove = parseArgValues(D, Arg, true);
- AllRemove |= expandGroups(Remove);
+ SanitizerMask Remove = parseArgValues(D, Arg, true);
+ AllRemove |= expandSanitizerGroups(Remove);
}
}
- addAllOf(Sanitizers, Kinds);
+
+ // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
+ // is disabled.
+ if ((Kinds & Vptr) &&
+ (RTTIMode == ToolChain::RM_DisabledImplicitly ||
+ RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ Kinds &= ~Vptr;
+ }
+
+ // Check that LTO is enabled if we need it.
+ if ((Kinds & NeedsLTO) && !D.IsUsingLTO(Args)) {
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
+ }
+
+ // Report error if there are non-trapping sanitizers that require
+ // c++abi-specific parts of UBSan runtime, and they are not provided by the
+ // toolchain. We don't have a good way to check the latter, so we just
+ // check if the toolchan supports vptr.
+ if (~Supported & Vptr) {
+ 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)
+ << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
+ Kinds &= ~KindsToDiagnose;
+ }
+ }
+
+ // Warn about incompatible groups of sanitizers.
+ std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
+ std::make_pair(Address, Thread), std::make_pair(Address, Memory),
+ std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
+ std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
+ std::make_pair(KernelAddress, Leak),
+ std::make_pair(KernelAddress, Thread),
+ std::make_pair(KernelAddress, Memory)};
+ for (auto G : IncompatibleGroups) {
+ SanitizerMask Group = G.first;
+ if (Kinds & Group) {
+ if (SanitizerMask Incompatible = Kinds & G.second) {
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForMask(D, Args, Group)
+ << lastArgumentForMask(D, Args, Incompatible);
+ Kinds &= ~Incompatible;
+ }
+ }
+ }
+ // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
+ // -fsanitize=address. Perhaps it should print an error, or perhaps
+ // -f(-no)sanitize=leak should change whether leak detection is enabled by
+ // default in ASan?
// Parse -f(no-)?sanitize-recover flags.
- unsigned RecoverableKinds = RecoverableByDefault;
- unsigned DiagnosedUnrecoverableKinds = 0;
+ SanitizerMask RecoverableKinds = RecoverableByDefault;
+ SanitizerMask DiagnosedUnrecoverableKinds = 0;
for (const auto *Arg : Args) {
+ const char *DeprecatedReplacement = nullptr;
if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
- // FIXME: Add deprecation notice, and then remove this flag.
- RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask);
+ DeprecatedReplacement = "-fsanitize-recover=undefined,integer";
+ RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
Arg->claim();
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
- // FIXME: Add deprecation notice, and then remove this flag.
- RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask);
+ DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
+ RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
Arg->claim();
} else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
- unsigned Add = parseArgValues(D, Arg, true);
+ SanitizerMask Add = parseArgValues(D, Arg, true);
// Report error if user explicitly tries to recover from unrecoverable
// sanitizer.
- if (unsigned KindsToDiagnose =
+ if (SanitizerMask KindsToDiagnose =
Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
SanitizerSet SetToDiagnose;
- addAllOf(SetToDiagnose, KindsToDiagnose);
+ SetToDiagnose.Mask |= KindsToDiagnose;
D.Diag(diag::err_drv_unsupported_option_argument)
<< Arg->getOption().getName() << toString(SetToDiagnose);
DiagnosedUnrecoverableKinds |= KindsToDiagnose;
}
- RecoverableKinds |= expandGroups(Add);
+ RecoverableKinds |= expandSanitizerGroups(Add);
Arg->claim();
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
- RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true));
+ RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
Arg->claim();
}
+ if (DeprecatedReplacement) {
+ D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
+ << DeprecatedReplacement;
+ }
}
RecoverableKinds &= Kinds;
RecoverableKinds &= ~Unrecoverable;
- addAllOf(RecoverableSanitizers, RecoverableKinds);
- UbsanTrapOnError =
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, false);
+ TrappingKinds &= Kinds;
- // Warn about undefined sanitizer options that require runtime support.
- if (UbsanTrapOnError && hasOneOf(Sanitizers, NotAllowedWithTrap)) {
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForMask(D, Args, NotAllowedWithTrap)
- << "-fsanitize-undefined-trap-on-error";
+ // Setup blacklist files.
+ // Add default blacklist from resource directory.
+ {
+ std::string BLPath;
+ if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
+ BlacklistFiles.push_back(BLPath);
}
-
- // Check for incompatible sanitizers.
- bool NeedsAsan = Sanitizers.has(SanitizerKind::Address);
- bool NeedsTsan = Sanitizers.has(SanitizerKind::Thread);
- bool NeedsMsan = Sanitizers.has(SanitizerKind::Memory);
- bool NeedsLsan = Sanitizers.has(SanitizerKind::Leak);
- if (NeedsAsan && NeedsTsan)
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, SanitizerKind::Address)
- << lastArgumentForKind(D, Args, SanitizerKind::Thread);
- if (NeedsAsan && NeedsMsan)
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, SanitizerKind::Address)
- << lastArgumentForKind(D, Args, SanitizerKind::Memory);
- if (NeedsTsan && NeedsMsan)
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, SanitizerKind::Thread)
- << lastArgumentForKind(D, Args, SanitizerKind::Memory);
- if (NeedsLsan && NeedsTsan)
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, SanitizerKind::Leak)
- << lastArgumentForKind(D, Args, SanitizerKind::Thread);
- if (NeedsLsan && NeedsMsan)
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, SanitizerKind::Leak)
- << lastArgumentForKind(D, Args, SanitizerKind::Memory);
- // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
- // -fsanitize=address. Perhaps it should print an error, or perhaps
- // -f(-no)sanitize=leak should change whether leak detection is enabled by
- // default in ASan?
-
// Parse -f(no-)sanitize-blacklist options.
- if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist)) {
- if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- std::string BLPath = BLArg->getValue();
- if (llvm::sys::fs::exists(BLPath)) {
- // Validate the blacklist format.
- std::string BLError;
- std::unique_ptr<llvm::SpecialCaseList> SCL(
- llvm::SpecialCaseList::create(BLPath, BLError));
- if (!SCL.get())
- D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
- else
- BlacklistFile = BLPath;
- } else {
+ for (const auto *Arg : Args) {
+ if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+ Arg->claim();
+ std::string BLPath = Arg->getValue();
+ if (llvm::sys::fs::exists(BLPath))
+ BlacklistFiles.push_back(BLPath);
+ else
D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
- }
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
+ Arg->claim();
+ BlacklistFiles.clear();
}
- } else {
- // If no -fsanitize-blacklist option is specified, try to look up for
- // blacklist in the resource directory.
- std::string BLPath;
- if (getDefaultBlacklist(D, BLPath) && llvm::sys::fs::exists(BLPath))
- BlacklistFile = BLPath;
+ }
+ // Validate blacklists format.
+ {
+ std::string BLError;
+ std::unique_ptr<llvm::SpecialCaseList> SCL(
+ llvm::SpecialCaseList::create(BlacklistFiles, BLError));
+ if (!SCL.get())
+ D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
}
// Parse -f[no-]sanitize-memory-track-origins[=level] options.
- if (NeedsMsan) {
+ if (AllAddedKinds & Memory) {
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
options::OPT_fsanitize_memory_track_origins,
options::OPT_fno_sanitize_memory_track_origins)) {
if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
- MsanTrackOrigins = 1;
+ MsanTrackOrigins = 2;
} else if (A->getOption().matches(
options::OPT_fno_sanitize_memory_track_origins)) {
MsanTrackOrigins = 0;
@@ -328,20 +418,76 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
}
+ MsanUseAfterDtor =
+ Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
}
- // Parse -fsanitize-coverage=N. Currently one of asan/msan/lsan is required.
- if (hasOneOf(Sanitizers, SupportsCoverage)) {
- if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) {
- StringRef S = A->getValue();
- // Legal values are 0..4.
- if (S.getAsInteger(0, SanitizeCoverage) || SanitizeCoverage < 0 ||
- SanitizeCoverage > 4)
- D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
+ // enabled sanitizers.
+ if (AllAddedKinds & SupportsCoverage) {
+ for (const auto *Arg : Args) {
+ if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
+ Arg->claim();
+ int LegacySanitizeCoverage;
+ if (Arg->getNumValues() == 1 &&
+ !StringRef(Arg->getValue(0))
+ .getAsInteger(0, LegacySanitizeCoverage) &&
+ LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
+ // TODO: Add deprecation notice for this form.
+ switch (LegacySanitizeCoverage) {
+ case 0:
+ CoverageFeatures = 0;
+ break;
+ case 1:
+ CoverageFeatures = CoverageFunc;
+ break;
+ case 2:
+ CoverageFeatures = CoverageBB;
+ break;
+ case 3:
+ CoverageFeatures = CoverageEdge;
+ break;
+ case 4:
+ CoverageFeatures = CoverageEdge | CoverageIndirCall;
+ break;
+ }
+ continue;
+ }
+ CoverageFeatures |= parseCoverageFeatures(D, Arg);
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
+ Arg->claim();
+ CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
+ }
}
}
-
- if (NeedsAsan) {
+ // Choose at most one coverage type: function, bb, or edge.
+ if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-coverage=func"
+ << "-fsanitize-coverage=bb";
+ if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-coverage=func"
+ << "-fsanitize-coverage=edge";
+ if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-coverage=bb"
+ << "-fsanitize-coverage=edge";
+ // Basic block tracing and 8-bit counters require some type of coverage
+ // enabled.
+ int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
+ if ((CoverageFeatures & CoverageTraceBB) &&
+ !(CoverageFeatures & CoverageTypes))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fsanitize-coverage=trace-bb"
+ << "-fsanitize-coverage=(func|bb|edge)";
+ if ((CoverageFeatures & Coverage8bitCounters) &&
+ !(CoverageFeatures & CoverageTypes))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fsanitize-coverage=8bit-counters"
+ << "-fsanitize-coverage=(func|bb|edge)";
+
+ if (AllAddedKinds & Address) {
AsanSharedRuntime =
Args.hasArg(options::OPT_shared_libasan) ||
(TC.getTriple().getEnvironment() == llvm::Triple::Android);
@@ -367,7 +513,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
case options::OPT__SLASH_LDd:
D.Diag(clang::diag::err_drv_argument_not_allowed_with)
<< WindowsDebugRTArg->getAsString(Args)
- << lastArgumentForKind(D, Args, SanitizerKind::Address);
+ << lastArgumentForMask(D, Args, Address);
D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
}
}
@@ -376,12 +522,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Parse -link-cxx-sanitizer flag.
LinkCXXRuntimes =
Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
+
+ // Finally, initialize the set of available and recoverable sanitizers.
+ Sanitizers.Mask |= Kinds;
+ RecoverableSanitizers.Mask |= RecoverableKinds;
+ TrapSanitizers.Mask |= TrappingKinds;
}
static std::string toString(const clang::SanitizerSet &Sanitizers) {
std::string Res;
#define SANITIZER(NAME, ID) \
- if (Sanitizers.has(clang::SanitizerKind::ID)) { \
+ if (Sanitizers.has(ID)) { \
if (!Res.empty()) \
Res += ","; \
Res += NAME; \
@@ -390,8 +541,9 @@ static std::string toString(const clang::SanitizerSet &Sanitizers) {
return Res;
}
-void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
+void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ types::ID InputType) const {
if (Sanitizers.empty())
return;
CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
@@ -400,82 +552,80 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
toString(RecoverableSanitizers)));
- if (UbsanTrapOnError)
- CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
+ if (!TrapSanitizers.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
- if (!BlacklistFile.empty()) {
+ for (const auto &BLPath : BlacklistFiles) {
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
- BlacklistOpt += BlacklistFile;
+ BlacklistOpt += BLPath;
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
}
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)));
- if (SanitizeCoverage)
- CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage=" +
- llvm::utostr(SanitizeCoverage)));
- // Workaround for PR16386.
- if (Sanitizers.has(SanitizerKind::Memory))
- CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
-}
-
-bool SanitizerArgs::getDefaultBlacklist(const Driver &D, std::string &BLPath) {
- const char *BlacklistFile = nullptr;
- if (Sanitizers.has(SanitizerKind::Address))
- BlacklistFile = "asan_blacklist.txt";
- else if (Sanitizers.has(SanitizerKind::Memory))
- BlacklistFile = "msan_blacklist.txt";
- else if (Sanitizers.has(SanitizerKind::Thread))
- BlacklistFile = "tsan_blacklist.txt";
- else if (Sanitizers.has(SanitizerKind::DataFlow))
- BlacklistFile = "dfsan_abilist.txt";
-
- if (BlacklistFile) {
- SmallString<64> Path(D.ResourceDir);
- llvm::sys::path::append(Path, BlacklistFile);
- BLPath = Path.str();
- return true;
+ // Translate available CoverageFeatures to corresponding clang-cc1 flags.
+ std::pair<int, const char *> CoverageFlags[] = {
+ std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
+ std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
+ std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
+ std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
+ std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
+ std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
+ std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters")};
+ for (auto F : CoverageFlags) {
+ if (CoverageFeatures & F.first)
+ CmdArgs.push_back(Args.MakeArgString(F.second));
}
- return false;
-}
-unsigned parseValue(const char *Value) {
- unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
-#define SANITIZER(NAME, ID) .Case(NAME, ID)
-#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group)
-#include "clang/Basic/Sanitizers.def"
- .Default(SanitizeKind());
- return ParsedKind;
-}
-unsigned expandGroups(unsigned Kinds) {
-#define SANITIZER(NAME, ID)
-#define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID;
-#include "clang/Basic/Sanitizers.def"
- return Kinds;
+ // MSan: Workaround for PR16386.
+ // ASan: This is mainly to help LSan with cases such as
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=373
+ // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
+ // affect compilation.
+ if (Sanitizers.has(Memory) || Sanitizers.has(Address))
+ CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
+
+ if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
+ // Instruct the code generator to embed linker directives in the object file
+ // that cause the required runtime libraries to be linked.
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + tools::getCompilerRT(TC, "ubsan_standalone")));
+ if (types::isCXX(InputType))
+ CmdArgs.push_back(
+ Args.MakeArgString("--dependent-lib=" +
+ tools::getCompilerRT(TC, "ubsan_standalone_cxx")));
+ }
}
-unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
- bool DiagnoseErrors) {
+SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors) {
assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
- A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
+ A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
+ A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
+ A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
"Invalid argument in parseArgValues!");
- unsigned Kinds = 0;
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
- const char *Value = A->getValue(I);
- unsigned Kind;
+ SanitizerMask Kinds = 0;
+ for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+ const char *Value = A->getValue(i);
+ SanitizerMask Kind;
// Special case: don't accept -fsanitize=all.
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
0 == strcmp("all", Value))
Kind = 0;
else
- Kind = parseValue(Value);
+ Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
if (Kind)
Kinds |= Kind;
@@ -486,34 +636,61 @@ unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
return Kinds;
}
+int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
+ assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
+ A->getOption().matches(options::OPT_fno_sanitize_coverage));
+ int Features = 0;
+ for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+ const char *Value = A->getValue(i);
+ int F = llvm::StringSwitch<int>(Value)
+ .Case("func", CoverageFunc)
+ .Case("bb", CoverageBB)
+ .Case("edge", CoverageEdge)
+ .Case("indirect-calls", CoverageIndirCall)
+ .Case("trace-bb", CoverageTraceBB)
+ .Case("trace-cmp", CoverageTraceCmp)
+ .Case("8bit-counters", Coverage8bitCounters)
+ .Default(0);
+ if (F == 0)
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ Features |= F;
+ }
+ return Features;
+}
+
std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
- unsigned Mask) {
+ SanitizerMask Mask) {
for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
E = Args.rend();
I != E; ++I) {
const auto *Arg = *I;
if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
- unsigned AddKinds = expandGroups(parseArgValues(D, Arg, false));
+ SanitizerMask AddKinds =
+ expandSanitizerGroups(parseArgValues(D, Arg, false));
if (AddKinds & Mask)
return describeSanitizeArg(Arg, Mask);
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
- unsigned RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
+ SanitizerMask RemoveKinds =
+ expandSanitizerGroups(parseArgValues(D, Arg, false));
Mask &= ~RemoveKinds;
}
}
llvm_unreachable("arg list didn't provide expected value");
}
-std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask) {
+std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
assert(A->getOption().matches(options::OPT_fsanitize_EQ)
&& "Invalid argument in describeSanitizerArg!");
std::string Sanitizers;
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
- if (expandGroups(parseValue(A->getValue(I))) & Mask) {
+ for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+ if (expandSanitizerGroups(
+ parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
+ Mask) {
if (!Sanitizers.empty())
Sanitizers += ",";
- Sanitizers += A->getValue(I);
+ Sanitizers += A->getValue(i);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index 2bcfecf..e6a1bc9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -26,14 +26,47 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
+static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
+ return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
+ options::OPT_fno_rtti, options::OPT_frtti);
+}
+
+static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
+ const llvm::Triple &Triple,
+ const Arg *CachedRTTIArg) {
+ // Explicit rtti/no-rtti args
+ if (CachedRTTIArg) {
+ if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
+ return ToolChain::RM_EnabledExplicitly;
+ else
+ return ToolChain::RM_DisabledExplicitly;
+ }
+
+ // -frtti is default, except for the PS4 CPU.
+ if (!Triple.isPS4CPU())
+ return ToolChain::RM_EnabledImplicitly;
+
+ // On the PS4, turning on c++ exceptions turns on rtti.
+ // We're assuming that, if we see -fexceptions, rtti gets turned on.
+ Arg *Exceptions = Args.getLastArgNoClaim(
+ options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions, options::OPT_fno_exceptions);
+ if (Exceptions &&
+ (Exceptions->getOption().matches(options::OPT_fexceptions) ||
+ Exceptions->getOption().matches(options::OPT_fcxx_exceptions)))
+ return ToolChain::RM_EnabledImplicitly;
+
+ return ToolChain::RM_DisabledImplicitly;
+}
+
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
- : D(D), Triple(T), Args(Args) {
+ : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
if (!isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
- << A->getValue()
- << A->getAsString(Args);
+ << A->getValue() << A->getAsString(Args);
}
ToolChain::~ToolChain() {
@@ -118,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:
@@ -264,18 +299,18 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
// '-mbig-endian'/'-EB'.
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian)) {
- if (A->getOption().matches(options::OPT_mlittle_endian))
- IsBigEndian = false;
- else
- IsBigEndian = true;
+ IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
}
// Thumb2 is the default for V7 on Darwin.
//
// FIXME: Thumb should just be another -target-feaure, not in the triple.
- StringRef Suffix = Triple.isOSBinFormatMachO()
- ? tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMCPUForMArch(Args, Triple))
- : tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMTargetCPU(Args, Triple));
+ std::string CPU = Triple.isOSBinFormatMachO()
+ ? tools::arm::getARMCPUForMArch(Args, Triple)
+ : tools::arm::getARMTargetCPU(Args, Triple);
+ StringRef Suffix =
+ tools::arm::getLLVMArchSuffixForARM(CPU,
+ tools::arm::getARMArch(Args, Triple));
bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
Suffix.startswith("v7em") ||
(Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
@@ -448,3 +483,12 @@ bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Path));
return true;
}
+
+SanitizerMask ToolChain::getSupportedSanitizers() const {
+ // Return sanitizers which don't require runtime support and are not
+ // platform or architecture-dependent.
+ using namespace SanitizerKind;
+ return (Undefined & ~Vptr & ~Function) | CFI | CFICastStrict |
+ UnsignedIntegerOverflow | LocalBounds;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index 8bd8298..15e36a1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -29,6 +29,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/TargetParser.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib> // ::getenv
#include <system_error>
@@ -38,13 +39,8 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
-MachO::MachO(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : ToolChain(D, Triple, Args) {
- getProgramPaths().push_back(getDriver().getInstalledDir());
- if (getDriver().getInstalledDir() != getDriver().Dir)
- getProgramPaths().push_back(getDriver().Dir);
-
+MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -52,28 +48,8 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple,
}
/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin::Darwin(const Driver & D, const llvm::Triple & Triple,
- const ArgList & Args)
- : MachO(D, Triple, Args), TargetInitialized(false) {
- // Compute the initial Darwin version from the triple
- unsigned Major, Minor, Micro;
- if (!Triple.getMacOSXVersion(Major, Minor, Micro))
- getDriver().Diag(diag::err_drv_invalid_darwin_version) <<
- Triple.getOSName();
- llvm::raw_string_ostream(MacosxVersionMin)
- << Major << '.' << Minor << '.' << Micro;
-
- // FIXME: DarwinVersion is only used to find GCC's libexec directory.
- // It should be removed when we stop supporting that.
- DarwinVersion[0] = Minor + 4;
- DarwinVersion[1] = Micro;
- DarwinVersion[2] = 0;
-
- // Compute the initial iOS version from the triple
- Triple.getiOSVersion(Major, Minor, Micro);
- llvm::raw_string_ostream(iOSVersionMin)
- << Major << '.' << Minor << '.' << Micro;
-}
+Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : MachO(D, Triple, Args), TargetInitialized(false) {}
types::ID MachO::LookupTypeForExtension(const char *Ext) const {
types::ID Ty = types::lookupTypeForExtension(Ext);
@@ -85,9 +61,7 @@ types::ID MachO::LookupTypeForExtension(const char *Ext) const {
return Ty;
}
-bool MachO::HasNativeLLVMSupport() const {
- return true;
-}
+bool MachO::HasNativeLLVMSupport() const { return true; }
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
@@ -108,38 +82,44 @@ bool Darwin::hasBlocksRuntime() const {
}
}
-static const char *GetArmArchForMArch(StringRef Value) {
- return llvm::StringSwitch<const char*>(Value)
- .Case("armv6k", "armv6")
- .Case("armv6m", "armv6m")
- .Case("armv5tej", "armv5")
- .Case("xscale", "xscale")
- .Case("armv4t", "armv4t")
- .Case("armv7", "armv7")
- .Cases("armv7a", "armv7-a", "armv7")
- .Cases("armv7r", "armv7-r", "armv7")
- .Cases("armv7em", "armv7e-m", "armv7em")
- .Cases("armv7k", "armv7-k", "armv7k")
- .Cases("armv7m", "armv7-m", "armv7m")
- .Cases("armv7s", "armv7-s", "armv7s")
- .Default(nullptr);
-}
-
-static const char *GetArmArchForMCpu(StringRef Value) {
- return llvm::StringSwitch<const char *>(Value)
- .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5")
- .Cases("arm10e", "arm10tdmi", "armv5")
- .Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5")
- .Case("xscale", "xscale")
- .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
- .Case("cortex-m0", "armv6m")
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7")
- .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "armv7")
- .Cases("cortex-r4", "cortex-r5", "armv7r")
- .Case("cortex-m3", "armv7m")
- .Cases("cortex-m4", "cortex-m7", "armv7em")
- .Case("swift", "armv7s")
- .Default(nullptr);
+// This is just a MachO name translation routine and there's no
+// way to join this into ARMTargetParser without breaking all
+// other assumptions. Maybe MachO should consider standardising
+// their nomenclature.
+static const char *ArmMachOArchName(StringRef Arch) {
+ return llvm::StringSwitch<const char *>(Arch)
+ .Case("armv6k", "armv6")
+ .Case("armv6m", "armv6m")
+ .Case("armv5tej", "armv5")
+ .Case("xscale", "xscale")
+ .Case("armv4t", "armv4t")
+ .Case("armv7", "armv7")
+ .Cases("armv7a", "armv7-a", "armv7")
+ .Cases("armv7r", "armv7-r", "armv7")
+ .Cases("armv7em", "armv7e-m", "armv7em")
+ .Cases("armv7k", "armv7-k", "armv7k")
+ .Cases("armv7m", "armv7-m", "armv7m")
+ .Cases("armv7s", "armv7-s", "armv7s")
+ .Default(nullptr);
+}
+
+static const char *ArmMachOArchNameCPU(StringRef CPU) {
+ unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
+ if (ArchKind == llvm::ARM::AK_INVALID)
+ return nullptr;
+ StringRef Arch = llvm::ARMTargetParser::getArchName(ArchKind);
+
+ // FIXME: Make sure this MachO triple mangling is really necessary.
+ // ARMv5* normalises to ARMv5.
+ if (Arch.startswith("armv5"))
+ Arch = Arch.substr(0, 5);
+ // ARMv6*, except ARMv6M, normalises to ARMv6.
+ else if (Arch.startswith("armv6") && !Arch.endswith("6m"))
+ Arch = Arch.substr(0, 5);
+ // ARMv7A normalises to ARMv7.
+ else if (Arch.endswith("v7a"))
+ Arch = Arch.substr(0, 5);
+ return Arch.data();
}
static bool isSoftFloatABI(const ArgList &Args) {
@@ -164,11 +144,11 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
case llvm::Triple::thumb:
case llvm::Triple::arm: {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
- if (const char *Arch = GetArmArchForMArch(A->getValue()))
+ if (const char *Arch = ArmMachOArchName(A->getValue()))
return Arch;
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- if (const char *Arch = GetArmArchForMCpu(A->getValue()))
+ if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
return Arch;
return "arm";
@@ -176,15 +156,12 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
}
}
-Darwin::~Darwin() {
-}
-
-MachO::~MachO() {
-}
+Darwin::~Darwin() {}
+MachO::~MachO() {}
std::string MachO::ComputeEffectiveClangTriple(const ArgList &Args,
- types::ID InputType) const {
+ types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
return Triple.getTriple();
@@ -228,18 +205,15 @@ Tool *MachO::getTool(Action::ActionClass AC) const {
}
}
-Tool *MachO::buildLinker() const {
- return new tools::darwin::Link(*this);
-}
+Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
Tool *MachO::buildAssembler() const {
- return new tools::darwin::Assemble(*this);
+ return new tools::darwin::Assembler(*this);
}
-DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
+DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Darwin(D, Triple, Args) {
-}
+ : Darwin(D, Triple, Args) {}
void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
// For iOS, 64-bit, promote certain warnings to errors.
@@ -302,8 +276,8 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build (unless
// we explicitly force linking with this library).
- if (AlwaysLink || llvm::sys::fs::exists(P.str()))
- CmdArgs.push_back(Args.MakeArgString(P.str()));
+ if (AlwaysLink || llvm::sys::fs::exists(P))
+ CmdArgs.push_back(Args.MakeArgString(P));
// Adding the rpaths might negatively interact when other rpaths are involved,
// so we should make sure we add the rpaths last, after all user-specified
@@ -320,7 +294,51 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
// Add the path to the resource dir to rpath to support using the dylib
// from the default location without copying.
CmdArgs.push_back("-rpath");
- CmdArgs.push_back(Args.MakeArgString(Dir.str()));
+ CmdArgs.push_back(Args.MakeArgString(Dir));
+ }
+}
+
+void Darwin::addProfileRTLibs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ 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) ||
+ Args.hasArg(options::OPT_coverage)))
+ return;
+
+ // Select the appropriate runtime library for the target.
+ if (isTargetIOSBased())
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a",
+ /*AlwaysLink*/ true);
+ else
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a",
+ /*AlwaysLink*/ true);
+}
+
+void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ StringRef Sanitizer) const {
+ if (!Args.hasArg(options::OPT_dynamiclib) &&
+ !Args.hasArg(options::OPT_bundle)) {
+ // Sanitizer runtime libraries requires C++.
+ AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
+ assert(isTargetMacOS() || isTargetIOSSimulator());
+ StringRef OS = isTargetMacOS() ? "osx" : "iossim";
+ AddLinkRuntimeLib(
+ Args, CmdArgs,
+ (Twine("libclang_rt.") + Sanitizer + "_" + OS + "_dynamic.dylib").str(),
+ /*AlwaysLink*/ true, /*IsEmbedded*/ false,
+ /*AddRPath*/ true);
+
+ if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
+ // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export
+ // all RTTI-related symbols that UBSan uses.
+ CmdArgs.push_back("-lc++abi");
}
}
@@ -332,7 +350,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
break;
default:
getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
- << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
+ << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
return;
}
@@ -347,70 +365,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
// cares. This is useful in situations where someone wants to statically link
// something like libstdc++, and needs its runtime support routines.
if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
- getDriver().Diag(diag::err_drv_unsupported_opt)
- << A->getAsString(Args);
+ getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
return;
}
- // If we are building profile support, link that library in.
- if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
- Args.hasArg(options::OPT_fprofile_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage)) {
- // Select the appropriate runtime library for the target.
- if (isTargetIOSBased())
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
- else
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a");
- }
-
const SanitizerArgs &Sanitize = getSanitizerArgs();
-
- // Add Ubsan runtime library, if required.
- if (Sanitize.needsUbsanRt()) {
- // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
- if (isTargetIOSBased()) {
- getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
- << "-fsanitize=undefined";
- } else {
- assert(isTargetMacOS() && "unexpected non OS X target");
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true);
-
- // The Ubsan runtime library requires C++.
- AddCXXStdlibLibArgs(Args, CmdArgs);
- }
- }
-
- // Add ASAN runtime library, if required. Dynamic libraries and bundles
- // should not be linked with the runtime library.
- if (Sanitize.needsAsanRt()) {
- // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
- if (isTargetIPhoneOS()) {
- getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
- << "-fsanitize=address";
- } else {
- if (!Args.hasArg(options::OPT_dynamiclib) &&
- !Args.hasArg(options::OPT_bundle)) {
- // The ASAN runtime library requires C++.
- AddCXXStdlibLibArgs(Args, CmdArgs);
- }
- if (isTargetMacOS()) {
- AddLinkRuntimeLib(Args, CmdArgs,
- "libclang_rt.asan_osx_dynamic.dylib",
- /*AlwaysLink*/ true, /*IsEmbedded*/ false,
- /*AddRPath*/ true);
- } else {
- if (isTargetIOSSimulator()) {
- AddLinkRuntimeLib(Args, CmdArgs,
- "libclang_rt.asan_iossim_dynamic.dylib",
- /*AlwaysLink*/ true, /*IsEmbedded*/ false,
- /*AddRPath*/ true);
- }
- }
- }
- }
+ if (Sanitize.needsAsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
+ if (Sanitize.needsUbsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
@@ -471,7 +434,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) &&
StringRef(env) != "/") {
Args.append(Args.MakeSeparateArg(
- nullptr, Opts.getOption(options::OPT_isysroot), env));
+ nullptr, Opts.getOption(options::OPT_isysroot), env));
}
}
}
@@ -481,39 +444,66 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (OSXVersion && iOSVersion) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << OSXVersion->getAsString(Args)
- << iOSVersion->getAsString(Args);
+ << OSXVersion->getAsString(Args) << iOSVersion->getAsString(Args);
iOSVersion = nullptr;
} else if (!OSXVersion && !iOSVersion) {
// If no deployment target was specified on the command line, check for
// environment defines.
- StringRef OSXTarget;
- StringRef iOSTarget;
+ std::string OSXTarget;
+ std::string iOSTarget;
if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
OSXTarget = env;
if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
iOSTarget = env;
- // If no '-miphoneos-version-min' specified on the command line and
- // IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default
- // based on -isysroot.
- if (iOSTarget.empty()) {
+ // If there is no command-line argument to specify the Target version and
+ // no environment variable defined, see if we can set the default based
+ // on -isysroot.
+ if (iOSTarget.empty() && OSXTarget.empty() &&
+ Args.hasArg(options::OPT_isysroot)) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- StringRef first, second;
StringRef isysroot = A->getValue();
- std::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS"));
- if (second != "")
- iOSTarget = second.substr(0,3);
+ // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
+ size_t BeginSDK = isysroot.rfind("SDKs/");
+ size_t EndSDK = isysroot.rfind(".sdk");
+ if (BeginSDK != StringRef::npos && EndSDK != StringRef::npos) {
+ StringRef SDK = isysroot.slice(BeginSDK + 5, EndSDK);
+ // Slice the version number out.
+ // Version number is between the first and the last number.
+ size_t StartVer = SDK.find_first_of("0123456789");
+ size_t EndVer = SDK.find_last_of("0123456789");
+ if (StartVer != StringRef::npos && EndVer > StartVer) {
+ StringRef Version = SDK.slice(StartVer, EndVer + 1);
+ if (SDK.startswith("iPhoneOS") ||
+ SDK.startswith("iPhoneSimulator"))
+ iOSTarget = Version;
+ else if (SDK.startswith("MacOSX"))
+ OSXTarget = Version;
+ }
+ }
}
}
- // If no OSX or iOS target has been specified and we're compiling for armv7,
- // go ahead as assume we're targeting iOS.
- StringRef MachOArchName = getMachOArchName(Args);
- if (OSXTarget.empty() && iOSTarget.empty() &&
- (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
- MachOArchName == "arm64"))
- iOSTarget = iOSVersionMin;
+ // If no OSX or iOS target has been specified, try to guess platform
+ // from arch name and compute the version from the triple.
+ if (OSXTarget.empty() && iOSTarget.empty()) {
+ StringRef MachOArchName = getMachOArchName(Args);
+ unsigned Major, Minor, Micro;
+ if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+ MachOArchName == "arm64") {
+ getTriple().getiOSVersion(Major, Minor, Micro);
+ llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.'
+ << Micro;
+ } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+ MachOArchName != "armv7em") {
+ if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) {
+ getDriver().Diag(diag::err_drv_invalid_darwin_version)
+ << getTriple().getOSName();
+ }
+ llvm::raw_string_ostream(OSXTarget) << Major << '.' << Minor << '.'
+ << Micro;
+ }
+ }
// Allow conflicts among OSX and iOS for historical reasons, but choose the
// default platform.
@@ -534,12 +524,6 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
Args.append(iOSVersion);
- } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
- MachOArchName != "armv7em") {
- // Otherwise, assume we are targeting OS X.
- const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(nullptr, O, MacosxVersionMin);
- Args.append(OSXVersion);
}
}
@@ -556,18 +540,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
bool HadExtra;
if (Platform == MacOS) {
assert(!iOSVersion && "Unknown target platform!");
- if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor,
- Micro, HadExtra) || HadExtra ||
- Major != 10 || Minor >= 100 || Micro >= 100)
+ if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro,
+ HadExtra) ||
+ HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << OSXVersion->getAsString(Args);
+ << OSXVersion->getAsString(Args);
} else if (Platform == IPhoneOS) {
assert(iOSVersion && "Unknown target platform!");
- if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor,
- Micro, HadExtra) || HadExtra ||
- Major >= 10 || Minor >= 100 || Micro >= 100)
+ if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro,
+ HadExtra) ||
+ HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << iOSVersion->getAsString(Args);
+ << iOSVersion->getAsString(Args);
} else
llvm_unreachable("unknown kind of Darwin platform");
@@ -599,11 +583,11 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
SmallString<128> P(A->getValue());
llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
- if (!llvm::sys::fs::exists(P.str())) {
+ if (!llvm::sys::fs::exists(P)) {
llvm::sys::path::remove_filename(P);
llvm::sys::path::append(P, "libstdc++.6.dylib");
- if (llvm::sys::fs::exists(P.str())) {
- CmdArgs.push_back(Args.MakeArgString(P.str()));
+ if (llvm::sys::fs::exists(P)) {
+ CmdArgs.push_back(Args.MakeArgString(P));
return;
}
}
@@ -646,8 +630,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
- if (llvm::sys::fs::exists(P.str()))
- CmdArgs.push_back(Args.MakeArgString(P.str()));
+ if (llvm::sys::fs::exists(P))
+ CmdArgs.push_back(Args.MakeArgString(P));
}
DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
@@ -667,10 +651,11 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
llvm::Triple::ArchType XarchArch =
- tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
- if (!(XarchArch == getArch() ||
- (BoundArch && XarchArch ==
- tools::darwin::getArchTypeForMachOArchName(BoundArch))))
+ tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
+ if (!(XarchArch == getArch() ||
+ (BoundArch &&
+ XarchArch ==
+ tools::darwin::getArchTypeForMachOArchName(BoundArch))))
continue;
Arg *OriginalArg = A;
@@ -688,11 +673,11 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
// 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);
+ << A->getAsString(Args);
continue;
} else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
- << A->getAsString(Args);
+ << A->getAsString(Args);
continue;
}
@@ -706,11 +691,9 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
// "input arguments".
if (A->getOption().hasFlag(options::LinkerInput)) {
// Convert the argument into individual Zlinker_input_args.
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
- DAL->AddSeparateArg(OriginalArg,
- Opts.getOption(options::OPT_Zlinker_input),
- A->getValue(i));
-
+ for (const char *Value : A->getValues()) {
+ DAL->AddSeparateArg(
+ OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
}
continue;
}
@@ -719,7 +702,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
// Sob. These is strictly gcc compatible for the time being. Apple
// gcc translates options twice, which means that self-expanding
// options add duplicates.
- switch ((options::ID) A->getOption().getID()) {
+ switch ((options::ID)A->getOption().getID()) {
default:
DAL->append(A);
break;
@@ -731,20 +714,19 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
break;
case options::OPT_dependency_file:
- DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF),
- A->getValue());
+ DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
break;
case options::OPT_gfull:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
- DAL->AddFlagArg(A,
- Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
+ DAL->AddFlagArg(
+ A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
break;
case options::OPT_gused:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
- DAL->AddFlagArg(A,
- Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
+ DAL->AddFlagArg(
+ A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
break;
case options::OPT_shared:
@@ -765,8 +747,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
break;
case options::OPT_Wno_nonportable_cfstrings:
- DAL->AddFlagArg(A,
- Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
+ DAL->AddFlagArg(
+ A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
break;
case options::OPT_fpascal_strings:
@@ -867,8 +849,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
return DAL;
}
-void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
+void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// Embedded targets are simple at the moment, not supporting sanitizers and
// with different libraries for each member of the product { static, PIC } x
// { hard-float, soft-float }
@@ -882,7 +864,6 @@ void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
}
-
DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const {
// First get the generic Apple args, before moving onto Darwin-specific ones.
@@ -903,7 +884,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
// but we can't check the deployment target in the translation code until
// it is set here.
if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) {
- for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
+ for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie;) {
Arg *A = *it;
++it;
if (A->getOption().getID() != options::OPT_mkernel &&
@@ -935,8 +916,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
where = "iOS 5.0";
if (where != StringRef()) {
- getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment)
- << where;
+ getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) << where;
}
}
@@ -959,13 +939,9 @@ bool Darwin::UseSjLjExceptions() const {
getTriple().getArch() == llvm::Triple::thumb);
}
-bool MachO::isPICDefault() const {
- return true;
-}
+bool MachO::isPICDefault() const { return true; }
-bool MachO::isPIEDefault() const {
- return false;
-}
+bool MachO::isPIEDefault() const { return false; }
bool MachO::isPICDefaultForced() const {
return (getArch() == llvm::Triple::x86_64 ||
@@ -977,8 +953,8 @@ bool MachO::SupportsProfiling() const {
return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64;
}
-void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
+void Darwin::addMinVersionArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
VersionTuple TargetVersion = getTargetVersion();
if (isTargetIOSSimulator())
@@ -993,8 +969,8 @@ void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}
-void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
+void Darwin::addStartObjectFileArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib)) {
// Derived from darwin_dylib1 spec.
@@ -1079,16 +1055,26 @@ void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args,
}
}
-bool Darwin::SupportsObjCGC() const {
- return isTargetMacOS();
-}
+bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); }
void Darwin::CheckObjCARC() const {
- if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
+ if (isTargetIOSBased() || (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
return;
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
+SanitizerMask Darwin::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ if (isTargetMacOS() || isTargetIOSSimulator())
+ Res |= SanitizerKind::Address;
+ if (isTargetMacOS()) {
+ if (!isMacosxVersionLT(10, 9))
+ Res |= SanitizerKind::Vptr;
+ Res |= SanitizerKind::SafeStack;
+ }
+ return Res;
+}
+
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
@@ -1098,17 +1084,15 @@ void Darwin::CheckObjCARC() const {
/// This is the primary means of forming GCCVersion objects.
/*static*/
Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
- const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
+ const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
- GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
- if (First.first.getAsInteger(10, GoodVersion.Major) ||
- GoodVersion.Major < 0)
+ GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
+ if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0)
return BadVersion;
GoodVersion.MajorStr = First.first.str();
- if (Second.first.getAsInteger(10, GoodVersion.Minor) ||
- GoodVersion.Minor < 0)
+ if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
return BadVersion;
GoodVersion.MinorStr = Second.first.str();
@@ -1185,12 +1169,11 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
/// should instead pull the target out of the driver. This is currently
/// necessary because the driver doesn't store the final version of the target
/// triple.
-void
-Generic_GCC::GCCInstallationDetector::init(
+void Generic_GCC::GCCInstallationDetector::init(
const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
- llvm::Triple BiarchVariantTriple =
- TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
- : TargetTriple.get32BitArchVariant();
+ llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
+ ? TargetTriple.get64BitArchVariant()
+ : TargetTriple.get32BitArchVariant();
// The library directories which may contain GCC installations.
SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
// The compatible GCC triples for this particular architecture.
@@ -1228,25 +1211,22 @@ Generic_GCC::GCCInstallationDetector::init(
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
Version = GCCVersion::Parse("0.0.0");
- for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
- if (!llvm::sys::fs::exists(Prefixes[i]))
+ for (const std::string &Prefix : Prefixes) {
+ if (!llvm::sys::fs::exists(Prefix))
continue;
- for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
- const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
+ for (const StringRef Suffix : CandidateLibDirs) {
+ const std::string LibDir = Prefix + Suffix.str();
if (!llvm::sys::fs::exists(LibDir))
continue;
- for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k)
- ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
- CandidateTripleAliases[k]);
+ for (const StringRef Candidate : CandidateTripleAliases)
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
}
- for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) {
- const std::string LibDir = Prefixes[i] + CandidateBiarchLibDirs[j].str();
+ for (const StringRef Suffix : CandidateBiarchLibDirs) {
+ const std::string LibDir = Prefix + Suffix.str();
if (!llvm::sys::fs::exists(LibDir))
continue;
- for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke;
- ++k)
- ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
- CandidateBiarchTripleAliases[k],
+ for (const StringRef Candidate : CandidateBiarchTripleAliases)
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate,
/*NeedsBiarchSuffix=*/ true);
}
}
@@ -1283,91 +1263,82 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
// Declare a bunch of static data sets that we'll select between below. These
// are specifically designed to always refer to string literals to avoid any
// lifetime or initialization issues.
- static const char *const AArch64LibDirs[] = { "/lib64", "/lib" };
- static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu",
- "aarch64-linux-gnu",
- "aarch64-linux-android",
- "aarch64-redhat-linux" };
- static const char *const AArch64beLibDirs[] = { "/lib" };
- static const char *const AArch64beTriples[] = { "aarch64_be-none-linux-gnu",
- "aarch64_be-linux-gnu" };
-
- static const char *const ARMLibDirs[] = { "/lib" };
- static const char *const ARMTriples[] = { "arm-linux-gnueabi",
- "arm-linux-androideabi" };
- static const char *const ARMHFTriples[] = { "arm-linux-gnueabihf",
- "armv7hl-redhat-linux-gnueabi" };
- static const char *const ARMebLibDirs[] = { "/lib" };
- static const char *const ARMebTriples[] = { "armeb-linux-gnueabi",
- "armeb-linux-androideabi" };
- static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf",
- "armebv7hl-redhat-linux-gnueabi" };
-
- static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
+ static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
+ static const char *const AArch64Triples[] = {
+ "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-linux-android",
+ "aarch64-redhat-linux"};
+ static const char *const AArch64beLibDirs[] = {"/lib"};
+ static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
+ "aarch64_be-linux-gnu"};
+
+ static const char *const ARMLibDirs[] = {"/lib"};
+ static const char *const ARMTriples[] = {"arm-linux-gnueabi",
+ "arm-linux-androideabi"};
+ static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
+ "armv7hl-redhat-linux-gnueabi"};
+ static const char *const ARMebLibDirs[] = {"/lib"};
+ static const char *const ARMebTriples[] = {"armeb-linux-gnueabi",
+ "armeb-linux-androideabi"};
+ static const char *const ARMebHFTriples[] = {
+ "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
+
+ static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
static const char *const X86_64Triples[] = {
- "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-pc-linux-gnu",
- "x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux",
- "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux",
- "x86_64-linux-android", "x86_64-unknown-linux"
- };
- static const char *const X32LibDirs[] = { "/libx32" };
- static const char *const X86LibDirs[] = { "/lib32", "/lib" };
+ "x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
+ "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
+ "x86_64-redhat-linux", "x86_64-suse-linux",
+ "x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
+ "x86_64-slackware-linux", "x86_64-linux-android",
+ "x86_64-unknown-linux"};
+ static const char *const X32LibDirs[] = {"/libx32"};
+ static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
- "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", "i386-linux-gnu",
- "i386-redhat-linux6E", "i686-redhat-linux", "i586-redhat-linux",
- "i386-redhat-linux", "i586-suse-linux", "i486-slackware-linux",
- "i686-montavista-linux", "i686-linux-android", "i586-linux-gnu"
- };
-
- static const char *const MIPSLibDirs[] = { "/lib" };
- static const char *const MIPSTriples[] = { "mips-linux-gnu",
- "mips-mti-linux-gnu",
- "mips-img-linux-gnu" };
- static const char *const MIPSELLibDirs[] = { "/lib" };
- static const char *const MIPSELTriples[] = { "mipsel-linux-gnu",
- "mipsel-linux-android",
- "mips-img-linux-gnu" };
-
- static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
- static const char *const MIPS64Triples[] = { "mips64-linux-gnu",
- "mips-mti-linux-gnu",
- "mips-img-linux-gnu",
- "mips64-linux-gnuabi64" };
- static const char *const MIPS64ELLibDirs[] = { "/lib64", "/lib" };
- static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu",
- "mips-mti-linux-gnu",
- "mips-img-linux-gnu",
- "mips64el-linux-android",
- "mips64el-linux-gnuabi64" };
-
- static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
+ "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu",
+ "i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
+ "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
+ "i486-slackware-linux", "i686-montavista-linux", "i686-linux-android",
+ "i586-linux-gnu"};
+
+ static const char *const MIPSLibDirs[] = {"/lib"};
+ static const char *const MIPSTriples[] = {
+ "mips-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu"};
+ static const char *const MIPSELLibDirs[] = {"/lib"};
+ static const char *const MIPSELTriples[] = {
+ "mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"};
+
+ static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
+ static const char *const MIPS64Triples[] = {
+ "mips64-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
+ "mips64-linux-gnuabi64"};
+ static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
+ static const char *const MIPS64ELTriples[] = {
+ "mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
+ "mips64el-linux-android", "mips64el-linux-gnuabi64"};
+
+ static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
- "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
- "powerpc-suse-linux", "powerpc-montavista-linuxspe"
- };
- static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
- static const char *const PPC64Triples[] = { "powerpc64-linux-gnu",
- "powerpc64-unknown-linux-gnu",
- "powerpc64-suse-linux",
- "ppc64-redhat-linux" };
- static const char *const PPC64LELibDirs[] = { "/lib64", "/lib" };
- static const char *const PPC64LETriples[] = { "powerpc64le-linux-gnu",
- "powerpc64le-unknown-linux-gnu",
- "powerpc64le-suse-linux",
- "ppc64le-redhat-linux" };
-
- static const char *const SPARCv8LibDirs[] = { "/lib32", "/lib" };
- static const char *const SPARCv8Triples[] = { "sparc-linux-gnu",
- "sparcv8-linux-gnu" };
- static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" };
- static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu",
- "sparcv9-linux-gnu" };
-
- static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
+ "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
+ "powerpc-suse-linux", "powerpc-montavista-linuxspe"};
+ static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};
+ static const char *const PPC64Triples[] = {
+ "powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu",
+ "powerpc64-suse-linux", "ppc64-redhat-linux"};
+ static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"};
+ static const char *const PPC64LETriples[] = {
+ "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu",
+ "powerpc64le-suse-linux", "ppc64le-redhat-linux"};
+
+ static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
+ static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
+ "sparcv8-linux-gnu"};
+ static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
+ static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
+ "sparcv9-linux-gnu"};
+
+ static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
static const char *const SystemZTriples[] = {
- "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
- "s390x-suse-linux", "s390x-redhat-linux"
- };
+ "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
+ "s390x-suse-linux", "s390x-redhat-linux"};
using std::begin;
using std::end;
@@ -1498,11 +1469,12 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
namespace {
// Filter to remove Multilibs that don't exist as a suffix to Path
-class FilterNonExistent : public MultilibSet::FilterCallback {
- std::string Base;
+class FilterNonExistent {
+ StringRef Base;
+
public:
- FilterNonExistent(std::string Base) : Base(Base) {}
- bool operator()(const Multilib &M) const override {
+ FilterNonExistent(StringRef Base) : Base(Base) {}
+ bool operator()(const Multilib &M) {
return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o");
}
};
@@ -1534,14 +1506,12 @@ static bool isMipsEL(llvm::Triple::ArchType Arch) {
}
static bool isMips16(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_mips16,
- options::OPT_mno_mips16);
+ Arg *A = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
return A && A->getOption().matches(options::OPT_mips16);
}
static bool isMicroMips(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_mmicromips,
- options::OPT_mno_micromips);
+ Arg *A = Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
return A && A->getOption().matches(options::OPT_mmicromips);
}
@@ -1562,8 +1532,7 @@ static Multilib makeMultilib(StringRef commonSuffix) {
}
static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
- const llvm::opt::ArgList &Args,
- DetectedMultilibs &Result) {
+ const ArgList &Args, DetectedMultilibs &Result) {
// Some MIPS toolchains put libraries and object files compiled
// using different options in to the sub-directoris which names
// reflects the flags used for compilation. For example sysroot
@@ -1595,181 +1564,182 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
MultilibSet FSFMipsMultilibs;
{
auto MArchMips32 = makeMultilib("/mips32")
- .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32");
+ .flag("+m32")
+ .flag("-m64")
+ .flag("-mmicromips")
+ .flag("+march=mips32");
auto MArchMicroMips = makeMultilib("/micromips")
- .flag("+m32").flag("-m64").flag("+mmicromips");
+ .flag("+m32")
+ .flag("-m64")
+ .flag("+mmicromips");
auto MArchMips64r2 = makeMultilib("/mips64r2")
- .flag("-m32").flag("+m64").flag("+march=mips64r2");
+ .flag("-m32")
+ .flag("+m64")
+ .flag("+march=mips64r2");
- auto MArchMips64 = makeMultilib("/mips64")
- .flag("-m32").flag("+m64").flag("-march=mips64r2");
+ auto MArchMips64 = makeMultilib("/mips64").flag("-m32").flag("+m64").flag(
+ "-march=mips64r2");
auto MArchDefault = makeMultilib("")
- .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32r2");
-
- auto Mips16 = makeMultilib("/mips16")
- .flag("+mips16");
-
- auto UCLibc = makeMultilib("/uclibc")
- .flag("+muclibc");
-
- auto MAbi64 = makeMultilib("/64")
- .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
-
- auto BigEndian = makeMultilib("")
- .flag("+EB").flag("-EL");
-
- auto LittleEndian = makeMultilib("/el")
- .flag("+EL").flag("-EB");
-
- auto SoftFloat = makeMultilib("/sof")
- .flag("+msoft-float");
-
- auto Nan2008 = makeMultilib("/nan2008")
- .flag("+mnan=2008");
-
- FSFMipsMultilibs = MultilibSet()
- .Either(MArchMips32, MArchMicroMips,
- MArchMips64r2, MArchMips64, MArchDefault)
- .Maybe(UCLibc)
- .Maybe(Mips16)
- .FilterOut("/mips64/mips16")
- .FilterOut("/mips64r2/mips16")
- .FilterOut("/micromips/mips16")
- .Maybe(MAbi64)
- .FilterOut("/micromips/64")
- .FilterOut("/mips32/64")
- .FilterOut("^/64")
- .FilterOut("/mips16/64")
- .Either(BigEndian, LittleEndian)
- .Maybe(SoftFloat)
- .Maybe(Nan2008)
- .FilterOut(".*sof/nan2008")
- .FilterOut(NonExistent)
- .setIncludeDirsCallback([](
- StringRef InstallDir, StringRef TripleStr, const Multilib &M) {
- std::vector<std::string> Dirs;
- Dirs.push_back((InstallDir + "/include").str());
- std::string SysRootInc = InstallDir.str() + "/../../../../sysroot";
- if (StringRef(M.includeSuffix()).startswith("/uclibc"))
- Dirs.push_back(SysRootInc + "/uclibc/usr/include");
- else
- Dirs.push_back(SysRootInc + "/usr/include");
- return Dirs;
- });
+ .flag("+m32")
+ .flag("-m64")
+ .flag("-mmicromips")
+ .flag("+march=mips32r2");
+
+ auto Mips16 = makeMultilib("/mips16").flag("+mips16");
+
+ auto UCLibc = makeMultilib("/uclibc").flag("+muclibc");
+
+ auto MAbi64 =
+ makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+
+ auto BigEndian = makeMultilib("").flag("+EB").flag("-EL");
+
+ auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
+
+ auto SoftFloat = makeMultilib("/sof").flag("+msoft-float");
+
+ auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008");
+
+ FSFMipsMultilibs =
+ MultilibSet()
+ .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64,
+ MArchDefault)
+ .Maybe(UCLibc)
+ .Maybe(Mips16)
+ .FilterOut("/mips64/mips16")
+ .FilterOut("/mips64r2/mips16")
+ .FilterOut("/micromips/mips16")
+ .Maybe(MAbi64)
+ .FilterOut("/micromips/64")
+ .FilterOut("/mips32/64")
+ .FilterOut("^/64")
+ .FilterOut("/mips16/64")
+ .Either(BigEndian, LittleEndian)
+ .Maybe(SoftFloat)
+ .Maybe(Nan2008)
+ .FilterOut(".*sof/nan2008")
+ .FilterOut(NonExistent)
+ .setIncludeDirsCallback([](StringRef InstallDir,
+ StringRef TripleStr, const Multilib &M) {
+ std::vector<std::string> Dirs;
+ Dirs.push_back((InstallDir + "/include").str());
+ std::string SysRootInc =
+ InstallDir.str() + "/../../../../sysroot";
+ if (StringRef(M.includeSuffix()).startswith("/uclibc"))
+ Dirs.push_back(SysRootInc + "/uclibc/usr/include");
+ else
+ Dirs.push_back(SysRootInc + "/usr/include");
+ return Dirs;
+ });
}
// Check for Code Sourcery toolchain multilibs
MultilibSet CSMipsMultilibs;
{
- auto MArchMips16 = makeMultilib("/mips16")
- .flag("+m32").flag("+mips16");
+ auto MArchMips16 = makeMultilib("/mips16").flag("+m32").flag("+mips16");
- auto MArchMicroMips = makeMultilib("/micromips")
- .flag("+m32").flag("+mmicromips");
+ auto MArchMicroMips =
+ makeMultilib("/micromips").flag("+m32").flag("+mmicromips");
- auto MArchDefault = makeMultilib("")
- .flag("-mips16").flag("-mmicromips");
+ auto MArchDefault = makeMultilib("").flag("-mips16").flag("-mmicromips");
- auto UCLibc = makeMultilib("/uclibc")
- .flag("+muclibc");
+ auto UCLibc = makeMultilib("/uclibc").flag("+muclibc");
- auto SoftFloat = makeMultilib("/soft-float")
- .flag("+msoft-float");
+ auto SoftFloat = makeMultilib("/soft-float").flag("+msoft-float");
- auto Nan2008 = makeMultilib("/nan2008")
- .flag("+mnan=2008");
+ auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008");
- auto DefaultFloat = makeMultilib("")
- .flag("-msoft-float").flag("-mnan=2008");
+ auto DefaultFloat =
+ makeMultilib("").flag("-msoft-float").flag("-mnan=2008");
- auto BigEndian = makeMultilib("")
- .flag("+EB").flag("-EL");
+ auto BigEndian = makeMultilib("").flag("+EB").flag("-EL");
- auto LittleEndian = makeMultilib("/el")
- .flag("+EL").flag("-EB");
+ auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
// Note that this one's osSuffix is ""
auto MAbi64 = makeMultilib("")
- .gccSuffix("/64")
- .includeSuffix("/64")
- .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
-
- CSMipsMultilibs = MultilibSet()
- .Either(MArchMips16, MArchMicroMips, MArchDefault)
- .Maybe(UCLibc)
- .Either(SoftFloat, Nan2008, DefaultFloat)
- .FilterOut("/micromips/nan2008")
- .FilterOut("/mips16/nan2008")
- .Either(BigEndian, LittleEndian)
- .Maybe(MAbi64)
- .FilterOut("/mips16.*/64")
- .FilterOut("/micromips.*/64")
- .FilterOut(NonExistent)
- .setIncludeDirsCallback([](
- StringRef InstallDir, StringRef TripleStr, const Multilib &M) {
- std::vector<std::string> Dirs;
- Dirs.push_back((InstallDir + "/include").str());
- std::string SysRootInc =
- InstallDir.str() + "/../../../../" + TripleStr.str();
- if (StringRef(M.includeSuffix()).startswith("/uclibc"))
- Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include");
- else
- Dirs.push_back(SysRootInc + "/libc/usr/include");
- return Dirs;
- });
- }
-
- MultilibSet AndroidMipsMultilibs = MultilibSet()
- .Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
- .Maybe(Multilib("/mips-r6").flag("+march=mips32r6"))
- .FilterOut(NonExistent);
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+mabi=n64")
+ .flag("-mabi=n32")
+ .flag("-m32");
+
+ CSMipsMultilibs =
+ MultilibSet()
+ .Either(MArchMips16, MArchMicroMips, MArchDefault)
+ .Maybe(UCLibc)
+ .Either(SoftFloat, Nan2008, DefaultFloat)
+ .FilterOut("/micromips/nan2008")
+ .FilterOut("/mips16/nan2008")
+ .Either(BigEndian, LittleEndian)
+ .Maybe(MAbi64)
+ .FilterOut("/mips16.*/64")
+ .FilterOut("/micromips.*/64")
+ .FilterOut(NonExistent)
+ .setIncludeDirsCallback([](StringRef InstallDir,
+ StringRef TripleStr, const Multilib &M) {
+ std::vector<std::string> Dirs;
+ Dirs.push_back((InstallDir + "/include").str());
+ std::string SysRootInc =
+ InstallDir.str() + "/../../../../" + TripleStr.str();
+ if (StringRef(M.includeSuffix()).startswith("/uclibc"))
+ Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include");
+ else
+ Dirs.push_back(SysRootInc + "/libc/usr/include");
+ return Dirs;
+ });
+ }
+
+ MultilibSet AndroidMipsMultilibs =
+ MultilibSet()
+ .Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
+ .Maybe(Multilib("/mips-r6").flag("+march=mips32r6"))
+ .FilterOut(NonExistent);
MultilibSet DebianMipsMultilibs;
{
- Multilib MAbiN32 = Multilib()
- .gccSuffix("/n32")
- .includeSuffix("/n32")
- .flag("+mabi=n32");
+ Multilib MAbiN32 =
+ Multilib().gccSuffix("/n32").includeSuffix("/n32").flag("+mabi=n32");
Multilib M64 = Multilib()
- .gccSuffix("/64")
- .includeSuffix("/64")
- .flag("+m64").flag("-m32").flag("-mabi=n32");
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+m64")
+ .flag("-m32")
+ .flag("-mabi=n32");
- Multilib M32 = Multilib()
- .flag("-m64").flag("+m32").flag("-mabi=n32");
+ Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32");
- DebianMipsMultilibs = MultilibSet()
- .Either(M32, M64, MAbiN32)
- .FilterOut(NonExistent);
+ DebianMipsMultilibs =
+ MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent);
}
MultilibSet ImgMultilibs;
{
- auto Mips64r6 = makeMultilib("/mips64r6")
- .flag("+m64").flag("-m32");
+ auto Mips64r6 = makeMultilib("/mips64r6").flag("+m64").flag("-m32");
- auto LittleEndian = makeMultilib("/el")
- .flag("+EL").flag("-EB");
+ auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
- auto MAbi64 = makeMultilib("/64")
- .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+ auto MAbi64 =
+ makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
- ImgMultilibs = MultilibSet()
- .Maybe(Mips64r6)
- .Maybe(MAbi64)
- .Maybe(LittleEndian)
- .FilterOut(NonExistent)
- .setIncludeDirsCallback([](
- StringRef InstallDir, StringRef TripleStr, const Multilib &M) {
- std::vector<std::string> Dirs;
- Dirs.push_back((InstallDir + "/include").str());
- Dirs.push_back((InstallDir + "/../../../../sysroot/usr/include").str());
- return Dirs;
- });
+ ImgMultilibs =
+ MultilibSet()
+ .Maybe(Mips64r6)
+ .Maybe(MAbi64)
+ .Maybe(LittleEndian)
+ .FilterOut(NonExistent)
+ .setIncludeDirsCallback([](StringRef InstallDir,
+ StringRef TripleStr, const Multilib &M) {
+ std::vector<std::string> Dirs;
+ Dirs.push_back((InstallDir + "/include").str());
+ Dirs.push_back(
+ (InstallDir + "/../../../../sysroot/usr/include").str());
+ return Dirs;
+ });
}
StringRef CPUName;
@@ -1783,10 +1753,13 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
addMultilibFlag(isMips64(TargetArch), "m64", Flags);
addMultilibFlag(isMips16(Args), "mips16", Flags);
addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
- addMultilibFlag(CPUName == "mips32r2", "march=mips32r2", Flags);
+ addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
+ CPUName == "mips32r5",
+ "march=mips32r2", Flags);
addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags);
addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
- addMultilibFlag(CPUName == "mips64r2" || CPUName == "octeon",
+ addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
+ CPUName == "mips64r5" || CPUName == "octeon",
"march=mips64r2", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags);
@@ -1821,8 +1794,8 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
// Sort candidates. Toolchain that best meets the directories goes first.
// Then select the first toolchains matches command line flags.
- MultilibSet *candidates[] = { &DebianMipsMultilibs, &FSFMipsMultilibs,
- &CSMipsMultilibs };
+ MultilibSet *candidates[] = {&DebianMipsMultilibs, &FSFMipsMultilibs,
+ &CSMipsMultilibs};
std::sort(
std::begin(candidates), std::end(candidates),
[](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); });
@@ -1864,17 +1837,23 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
Multilib Default;
Multilib Alt64 = Multilib()
- .gccSuffix("/64")
- .includeSuffix("/64")
- .flag("-m32").flag("+m64").flag("-mx32");
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("-m32")
+ .flag("+m64")
+ .flag("-mx32");
Multilib Alt32 = Multilib()
- .gccSuffix("/32")
- .includeSuffix("/32")
- .flag("+m32").flag("-m64").flag("-mx32");
+ .gccSuffix("/32")
+ .includeSuffix("/32")
+ .flag("+m32")
+ .flag("-m64")
+ .flag("-mx32");
Multilib Altx32 = Multilib()
- .gccSuffix("/x32")
- .includeSuffix("/x32")
- .flag("-m32").flag("-m64").flag("+mx32");
+ .gccSuffix("/x32")
+ .includeSuffix("/x32")
+ .flag("-m32")
+ .flag("-m64")
+ .flag("+mx32");
FilterNonExistent NonExistent(Path);
@@ -1921,8 +1900,7 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
return false;
- if (Result.SelectedMultilib == Alt64 ||
- Result.SelectedMultilib == Alt32 ||
+ if (Result.SelectedMultilib == Alt64 || Result.SelectedMultilib == Alt32 ||
Result.SelectedMultilib == Altx32)
Result.BiarchSibling = Default;
@@ -1938,27 +1916,26 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// check for. We also record what is necessary to walk from each back
// up to the lib directory.
const std::string LibSuffixes[] = {
- "/gcc/" + CandidateTriple.str(),
- // Debian puts cross-compilers in gcc-cross
- "/gcc-cross/" + CandidateTriple.str(),
- "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
-
- // The Freescale PPC SDK has the gcc libraries in
- // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
- "/" + CandidateTriple.str(),
-
- // Ubuntu has a strange mis-matched pair of triples that this happens to
- // match.
- // FIXME: It may be worthwhile to generalize this and look for a second
- // triple.
- "/i386-linux-gnu/gcc/" + CandidateTriple.str()
- };
+ "/gcc/" + CandidateTriple.str(),
+ // Debian puts cross-compilers in gcc-cross
+ "/gcc-cross/" + CandidateTriple.str(),
+ "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+
+ // The Freescale PPC SDK has the gcc libraries in
+ // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
+ "/" + CandidateTriple.str(),
+
+ // Ubuntu has a strange mis-matched pair of triples that this happens to
+ // match.
+ // FIXME: It may be worthwhile to generalize this and look for a second
+ // triple.
+ "/i386-linux-gnu/gcc/" + CandidateTriple.str()};
const std::string InstallSuffixes[] = {
- "/../../..", // gcc/
- "/../../..", // gcc-cross/
- "/../../../..", // <triple>/gcc/
- "/../..", // <triple>/
- "/../../../.." // i386-linux-gnu/gcc/<triple>/
+ "/../../..", // gcc/
+ "/../../..", // gcc-cross/
+ "/../../../..", // <triple>/gcc/
+ "/../..", // <triple>/
+ "/../../../.." // i386-linux-gnu/gcc/<triple>/
};
// Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
const unsigned NumLibSuffixes =
@@ -2005,26 +1982,25 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
}
}
-Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
+Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), GCCInstallation() {
+ : ToolChain(D, Triple, Args), GCCInstallation() {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
-Generic_GCC::~Generic_GCC() {
-}
+Generic_GCC::~Generic_GCC() {}
Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::PreprocessJobClass:
if (!Preprocess)
- Preprocess.reset(new tools::gcc::Preprocess(*this));
+ Preprocess.reset(new tools::gcc::Preprocessor(*this));
return Preprocess.get();
case Action::CompileJobClass:
if (!Compile)
- Compile.reset(new tools::gcc::Compile(*this));
+ Compile.reset(new tools::gcc::Compiler(*this));
return Compile.get();
default:
return ToolChain::getTool(AC);
@@ -2032,12 +2008,10 @@ Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
}
Tool *Generic_GCC::buildAssembler() const {
- return new tools::gnutools::Assemble(*this);
+ return new tools::gnutools::Assembler(*this);
}
-Tool *Generic_GCC::buildLinker() const {
- return new tools::gcc::Link(*this);
-}
+Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
// Print the information about how we detected the GCC installation.
@@ -2049,32 +2023,38 @@ bool Generic_GCC::IsUnwindTablesDefault() const {
}
bool Generic_GCC::isPICDefault() const {
- return false;
+ return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
}
-bool Generic_GCC::isPIEDefault() const {
- return false;
-}
+bool Generic_GCC::isPIEDefault() const { return false; }
bool Generic_GCC::isPICDefaultForced() const {
- return false;
+ return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
}
bool Generic_GCC::IsIntegratedAssemblerDefault() const {
- return getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64 ||
- getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::aarch64_be ||
- getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::armeb ||
- getTriple().getArch() == llvm::Triple::thumb ||
- getTriple().getArch() == llvm::Triple::thumbeb ||
- getTriple().getArch() == llvm::Triple::ppc ||
- getTriple().getArch() == llvm::Triple::ppc64 ||
- getTriple().getArch() == llvm::Triple::ppc64le ||
- getTriple().getArch() == llvm::Triple::sparc ||
- getTriple().getArch() == llvm::Triple::sparcv9 ||
- getTriple().getArch() == llvm::Triple::systemz;
+ switch (getTriple().getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::bpfel:
+ case llvm::Triple::bpfeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::systemz:
+ return true;
+ default:
+ return false;
+ }
}
void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
@@ -2085,11 +2065,11 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getArch() == llvm::Triple::aarch64_be ||
(getTriple().getOS() == llvm::Triple::Linux &&
(!V.isOlderThan(4, 7, 0) ||
- getTriple().getEnvironment() == llvm::Triple::Android));
+ getTriple().getEnvironment() == llvm::Triple::Android)) ||
+ getTriple().getOS() == llvm::Triple::NaCl;
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array,
- UseInitArrayDefault))
+ options::OPT_fno_use_init_array, UseInitArrayDefault))
CC1Args.push_back("-fuse-init-array");
}
@@ -2115,26 +2095,38 @@ std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir,
return InstallRelDir;
}
-static void GetHexagonLibraryPaths(
- const ArgList &Args,
- const std::string &Ver,
- const std::string &MarchString,
- const std::string &InstalledDir,
- ToolChain::path_list *LibPaths)
-{
+const char *Hexagon_TC::GetSmallDataThreshold(const ArgList &Args) {
+ Arg *A;
+
+ A = Args.getLastArg(options::OPT_G, options::OPT_G_EQ,
+ options::OPT_msmall_data_threshold_EQ);
+ if (A)
+ return A->getValue();
+
+ A = Args.getLastArg(options::OPT_shared, options::OPT_fpic,
+ options::OPT_fPIC);
+ if (A)
+ return "0";
+
+ return 0;
+}
+
+bool Hexagon_TC::UsesG0(const char *smallDataThreshold) {
+ return smallDataThreshold && smallDataThreshold[0] == '0';
+}
+
+static void GetHexagonLibraryPaths(const ArgList &Args, const std::string &Ver,
+ const std::string &MarchString,
+ const std::string &InstalledDir,
+ ToolChain::path_list *LibPaths) {
bool buildingLib = Args.hasArg(options::OPT_shared);
//----------------------------------------------------------------------------
// -L Args
//----------------------------------------------------------------------------
- for (arg_iterator
- it = Args.filtered_begin(options::OPT_L),
- ie = Args.filtered_end();
- it != ie;
- ++it) {
- for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
- LibPaths->push_back((*it)->getValue(i));
- }
+ for (Arg *A : Args.filtered(options::OPT_L))
+ for (const char *Value : A->getValues())
+ LibPaths->push_back(Value);
//----------------------------------------------------------------------------
// Other standard paths
@@ -2168,7 +2160,7 @@ static void GetHexagonLibraryPaths(
Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Linux(D, Triple, Args) {
+ : Linux(D, Triple, Args) {
const std::string InstalledDir(getDriver().getInstalledDir());
const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir, Args);
@@ -2181,7 +2173,7 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
// Determine version of GCC libraries and headers to use.
const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon");
std::error_code ec;
- GCCVersion MaxVersion= GCCVersion::Parse("0.0.0");
+ GCCVersion MaxVersion = GCCVersion::Parse("0.0.0");
for (llvm::sys::fs::directory_iterator di(HexagonDir, ec), de;
!ec && di != de; di = di.increment(ec)) {
GCCVersion cv = GCCVersion::Parse(llvm::sys::path::filename(di->path()));
@@ -2190,30 +2182,25 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
}
GCCLibAndIncVersion = MaxVersion;
- ToolChain::path_list *LibPaths= &getFilePaths();
+ ToolChain::path_list *LibPaths = &getFilePaths();
// Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
// 'elf' OS type, so the Linux paths are not appropriate. When we actually
// support 'linux' we'll need to fix this up
LibPaths->clear();
- GetHexagonLibraryPaths(
- Args,
- GetGCCLibAndIncVersion(),
- GetTargetCPU(Args),
- InstalledDir,
- LibPaths);
+ GetHexagonLibraryPaths(Args, GetGCCLibAndIncVersion(), GetTargetCPU(Args),
+ InstalledDir, LibPaths);
}
-Hexagon_TC::~Hexagon_TC() {
-}
+Hexagon_TC::~Hexagon_TC() {}
Tool *Hexagon_TC::buildAssembler() const {
- return new tools::hexagon::Assemble(*this);
+ return new tools::hexagon::Assembler(*this);
}
Tool *Hexagon_TC::buildLinker() const {
- return new tools::hexagon::Link(*this);
+ return new tools::hexagon::Linker(*this);
}
void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -2246,7 +2233,7 @@ void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
llvm::sys::path::append(IncludeDir, Ver);
- addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
+ addSystemInclude(DriverArgs, CC1Args, IncludeDir);
}
ToolChain::CXXStdlibType
@@ -2257,8 +2244,7 @@ Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const {
StringRef Value = A->getValue();
if (Value != "libstdc++") {
- getDriver().Diag(diag::err_drv_invalid_stdlib_name)
- << A->getAsString(Args);
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
}
return ToolChain::CST_Libstdcxx;
@@ -2287,8 +2273,7 @@ static int getHexagonVersion(const ArgList &Args) {
return 4;
}
-StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
-{
+StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args) {
int V = getHexagonVersion(Args);
// FIXME: We don't support versions < 4. We should error on them.
switch (V) {
@@ -2308,13 +2293,187 @@ StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
}
// End Hexagon
+/// NaCl Toolchain
+NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ // Remove paths added by Generic_GCC. NaCl Toolchain cannot use the
+ // default paths, and must instead only use the paths provided
+ // with this toolchain based on architecture.
+ path_list &file_paths = getFilePaths();
+ path_list &prog_paths = getProgramPaths();
+
+ file_paths.clear();
+ prog_paths.clear();
+
+ // Path for library files (libc.a, ...)
+ std::string FilePath(getDriver().Dir + "/../");
+
+ // Path for tools (clang, ld, etc..)
+ std::string ProgPath(getDriver().Dir + "/../");
+
+ // Path for toolchain libraries (libgcc.a, ...)
+ std::string ToolPath(getDriver().ResourceDir + "/lib/");
+
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86: {
+ file_paths.push_back(FilePath + "x86_64-nacl/lib32");
+ file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32");
+ prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
+ file_paths.push_back(ToolPath + "i686-nacl");
+ break;
+ }
+ case llvm::Triple::x86_64: {
+ file_paths.push_back(FilePath + "x86_64-nacl/lib");
+ file_paths.push_back(FilePath + "x86_64-nacl/usr/lib");
+ prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
+ file_paths.push_back(ToolPath + "x86_64-nacl");
+ break;
+ }
+ case llvm::Triple::arm: {
+ file_paths.push_back(FilePath + "arm-nacl/lib");
+ file_paths.push_back(FilePath + "arm-nacl/usr/lib");
+ prog_paths.push_back(ProgPath + "arm-nacl/bin");
+ 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;
+ }
+
+ // Use provided linker, not system linker
+ Linker = GetProgramPath("ld");
+ NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s");
+}
+
+void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ SmallString<128> P(D.Dir + "/../");
+ switch (getTriple().getArch()) {
+ case llvm::Triple::arm:
+ llvm::sys::path::append(P, "arm-nacl/usr/include");
+ break;
+ case llvm::Triple::x86:
+ llvm::sys::path::append(P, "x86_64-nacl/usr/include");
+ break;
+ 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;
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+}
+
+void NaCl_TC::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Check for -stdlib= flags. We only support libc++ but this consumes the arg
+ // if the value is libc++, and emits an error for other values.
+ GetCXXStdlibType(Args);
+ CmdArgs.push_back("-lc++");
+}
+
+void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // Check for -stdlib= flags. We only support libc++ but this consumes the arg
+ // if the value is libc++, and emits an error for other values.
+ GetCXXStdlibType(DriverArgs);
+
+ SmallString<128> P(D.Dir + "/../");
+ switch (getTriple().getArch()) {
+ case llvm::Triple::arm:
+ llvm::sys::path::append(P, "arm-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
+ case llvm::Triple::x86:
+ llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
+ case llvm::Triple::x86_64:
+ 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;
+ }
+}
+
+ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libcxx;
+}
+
+std::string NaCl_TC::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType));
+ if (TheTriple.getArch() == llvm::Triple::arm &&
+ TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
+ TheTriple.setEnvironment(llvm::Triple::GNUEABIHF);
+ return TheTriple.getTriple();
+}
+
+Tool *NaCl_TC::buildLinker() const {
+ return new tools::nacltools::Linker(*this);
+}
+
+Tool *NaCl_TC::buildAssembler() const {
+ if (getTriple().getArch() == llvm::Triple::arm)
+ return new tools::nacltools::AssemblerARM(*this);
+ return new tools::gnutools::Assembler(*this);
+}
+// End NaCl
+
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
/// Currently does not support anything else but compilation.
-TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args) {
+ : ToolChain(D, Triple, Args) {
// Path mangling to find libexec
std::string Path(getDriver().Dir);
@@ -2322,59 +2481,78 @@ TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
getProgramPaths().push_back(Path);
}
-TCEToolChain::~TCEToolChain() {
-}
+TCEToolChain::~TCEToolChain() {}
-bool TCEToolChain::IsMathErrnoDefault() const {
- return true;
+bool TCEToolChain::IsMathErrnoDefault() const { return true; }
+
+bool TCEToolChain::isPICDefault() const { return false; }
+
+bool TCEToolChain::isPIEDefault() const { return false; }
+
+bool TCEToolChain::isPICDefaultForced() const { return false; }
+
+// CloudABI - CloudABI tool chain which can call ld(1) directly.
+
+CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ SmallString<128> P(getDriver().Dir);
+ llvm::sys::path::append(P, "..", getTriple().str(), "lib");
+ getFilePaths().push_back(P.str());
}
-bool TCEToolChain::isPICDefault() const {
- return false;
+void CloudABI::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) &&
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ SmallString<128> P(getDriver().Dir);
+ llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
}
-bool TCEToolChain::isPIEDefault() const {
- return false;
+void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lunwind");
}
-bool TCEToolChain::isPICDefaultForced() const {
- return false;
+Tool *CloudABI::buildLinker() const {
+ return new tools::cloudabi::Linker(*this);
}
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
-OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *OpenBSD::buildAssembler() const {
- return new tools::openbsd::Assemble(*this);
+ return new tools::openbsd::Assembler(*this);
}
-Tool *OpenBSD::buildLinker() const {
- return new tools::openbsd::Link(*this);
-}
+Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
-Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+Bitrig::Bitrig(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *Bitrig::buildAssembler() const {
- return new tools::bitrig::Assemble(*this);
+ return new tools::bitrig::Assembler(*this);
}
-Tool *Bitrig::buildLinker() const {
- return new tools::bitrig::Link(*this);
-}
+Tool *Bitrig::buildLinker() const { return new tools::bitrig::Linker(*this); }
-ToolChain::CXXStdlibType
-Bitrig::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType Bitrig::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libstdc++")
@@ -2382,8 +2560,7 @@ Bitrig::GetCXXStdlibType(const ArgList &Args) const {
if (Value == "libc++")
return ToolChain::CST_Libcxx;
- getDriver().Diag(diag::err_drv_invalid_stdlib_name)
- << A->getAsString(Args);
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
}
return ToolChain::CST_Libcxx;
}
@@ -2409,11 +2586,11 @@ void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
if (Triple.startswith("amd64"))
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" +
- Triple.substr(5));
+ Triple.substr(5));
else
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/stdc++/" +
- Triple);
+ addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot +
+ "/usr/include/c++/stdc++/" +
+ Triple);
break;
}
}
@@ -2434,8 +2611,9 @@ void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
-FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
// When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
// back to '/usr/lib' if it doesn't exist.
@@ -2447,8 +2625,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
-ToolChain::CXXStdlibType
-FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libstdc++")
@@ -2456,10 +2633,9 @@ FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Value == "libc++")
return ToolChain::CST_Libcxx;
- getDriver().Diag(diag::err_drv_invalid_stdlib_name)
- << A->getAsString(Args);
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
}
- if (getTriple().getOSMajorVersion() >= 10)
+ if (getTriple().getOSMajorVersion() >= 10)
return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx;
}
@@ -2485,12 +2661,10 @@ void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
Tool *FreeBSD::buildAssembler() const {
- return new tools::freebsd::Assemble(*this);
+ return new tools::freebsd::Assembler(*this);
}
-Tool *FreeBSD::buildLinker() const {
- return new tools::freebsd::Link(*this);
-}
+Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
bool FreeBSD::UseSjLjExceptions() const {
// FreeBSD uses SjLj exceptions on ARM oabi.
@@ -2506,18 +2680,32 @@ bool FreeBSD::UseSjLjExceptions() const {
}
}
-bool FreeBSD::HasNativeLLVMSupport() const {
- return true;
-}
+bool FreeBSD::HasNativeLLVMSupport() const { return true; }
+
+bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
-bool FreeBSD::isPIEDefault() const {
- return getSanitizerArgs().requiresPIE();
+SanitizerMask FreeBSD::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+ const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Vptr;
+ if (IsX86_64 || IsMIPS64) {
+ Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::Thread;
+ }
+ if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::SafeStack;
+ }
+ return Res;
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
-NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
if (getDriver().UseStdLib) {
// When targeting a 32-bit platform, try the special directory used on
@@ -2569,15 +2757,12 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
}
Tool *NetBSD::buildAssembler() const {
- return new tools::netbsd::Assemble(*this);
+ return new tools::netbsd::Assembler(*this);
}
-Tool *NetBSD::buildLinker() const {
- return new tools::netbsd::Link(*this);
-}
+Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
-ToolChain::CXXStdlibType
-NetBSD::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType NetBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libstdc++")
@@ -2585,8 +2770,7 @@ NetBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Value == "libc++")
return ToolChain::CST_Libcxx;
- getDriver().Diag(diag::err_drv_invalid_stdlib_name)
- << A->getAsString(Args);
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
}
unsigned Major, Minor, Micro;
@@ -2633,25 +2817,23 @@ void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
-Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+Minix::Minix(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *Minix::buildAssembler() const {
- return new tools::minix::Assemble(*this);
+ return new tools::minix::Assembler(*this);
}
-Tool *Minix::buildLinker() const {
- return new tools::minix::Link(*this);
-}
+Tool *Minix::buildLinker() const { return new tools::minix::Linker(*this); }
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
-Solaris::Solaris(const Driver &D, const llvm::Triple& Triple,
+Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Generic_GCC(D, Triple, Args) {
+ : Generic_GCC(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -2662,25 +2844,28 @@ Solaris::Solaris(const Driver &D, const llvm::Triple& Triple,
}
Tool *Solaris::buildAssembler() const {
- return new tools::solaris::Assemble(*this);
+ return new tools::solaris::Assembler(*this);
}
-Tool *Solaris::buildLinker() const {
- return new tools::solaris::Link(*this);
-}
+Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); }
/// Distribution (very bare-bones at the moment).
enum Distro {
+ // NB: Releases of a particular Linux distro should be kept together
+ // in this enum, because some tests are done by integer comparison against
+ // the first and last known member in the family, e.g. IsRedHat().
ArchLinux,
DebianLenny,
DebianSqueeze,
DebianWheezy,
DebianJessie,
+ DebianStretch,
Exherbo,
RHEL4,
RHEL5,
RHEL6,
+ RHEL7,
Fedora,
OpenSUSE,
UbuntuHardy,
@@ -2696,23 +2881,24 @@ enum Distro {
UbuntuRaring,
UbuntuSaucy,
UbuntuTrusty,
+ UbuntuUtopic,
+ UbuntuVivid,
+ UbuntuWily,
UnknownDistro
};
static bool IsRedhat(enum Distro Distro) {
- return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6);
+ return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL7);
}
-static bool IsOpenSUSE(enum Distro Distro) {
- return Distro == OpenSUSE;
-}
+static bool IsOpenSUSE(enum Distro Distro) { return Distro == OpenSUSE; }
static bool IsDebian(enum Distro Distro) {
- return Distro >= DebianLenny && Distro <= DebianJessie;
+ return Distro >= DebianLenny && Distro <= DebianStretch;
}
static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuTrusty;
+ return Distro >= UbuntuHardy && Distro <= UbuntuWily;
}
static Distro DetectDistro(llvm::Triple::ArchType Arch) {
@@ -2723,23 +2909,26 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
SmallVector<StringRef, 16> Lines;
Data.split(Lines, "\n");
Distro Version = UnknownDistro;
- for (unsigned i = 0, s = Lines.size(); i != s; ++i)
- if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME="))
- Version = llvm::StringSwitch<Distro>(Lines[i].substr(17))
- .Case("hardy", UbuntuHardy)
- .Case("intrepid", UbuntuIntrepid)
- .Case("jaunty", UbuntuJaunty)
- .Case("karmic", UbuntuKarmic)
- .Case("lucid", UbuntuLucid)
- .Case("maverick", UbuntuMaverick)
- .Case("natty", UbuntuNatty)
- .Case("oneiric", UbuntuOneiric)
- .Case("precise", UbuntuPrecise)
- .Case("quantal", UbuntuQuantal)
- .Case("raring", UbuntuRaring)
- .Case("saucy", UbuntuSaucy)
- .Case("trusty", UbuntuTrusty)
- .Default(UnknownDistro);
+ for (const StringRef Line : Lines)
+ if (Version == UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
+ Version = llvm::StringSwitch<Distro>(Line.substr(17))
+ .Case("hardy", UbuntuHardy)
+ .Case("intrepid", UbuntuIntrepid)
+ .Case("jaunty", UbuntuJaunty)
+ .Case("karmic", UbuntuKarmic)
+ .Case("lucid", UbuntuLucid)
+ .Case("maverick", UbuntuMaverick)
+ .Case("natty", UbuntuNatty)
+ .Case("oneiric", UbuntuOneiric)
+ .Case("precise", UbuntuPrecise)
+ .Case("quantal", UbuntuQuantal)
+ .Case("raring", UbuntuRaring)
+ .Case("saucy", UbuntuSaucy)
+ .Case("trusty", UbuntuTrusty)
+ .Case("utopic", UbuntuUtopic)
+ .Case("vivid", UbuntuVivid)
+ .Case("wily", UbuntuWily)
+ .Default(UnknownDistro);
return Version;
}
@@ -2750,7 +2939,9 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
return Fedora;
if (Data.startswith("Red Hat Enterprise Linux") ||
Data.startswith("CentOS")) {
- if (Data.find("release 6") != StringRef::npos)
+ if (Data.find("release 7") != StringRef::npos)
+ return RHEL7;
+ else if (Data.find("release 6") != StringRef::npos)
return RHEL6;
else if (Data.find("release 5") != StringRef::npos)
return RHEL5;
@@ -2767,10 +2958,12 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
return DebianLenny;
else if (Data.startswith("squeeze/sid") || Data[0] == '6')
return DebianSqueeze;
- else if (Data.startswith("wheezy/sid") || Data[0] == '7')
+ else if (Data.startswith("wheezy/sid") || Data[0] == '7')
return DebianWheezy;
- else if (Data.startswith("jessie/sid") || Data[0] == '8')
+ else if (Data.startswith("jessie/sid") || Data[0] == '8')
return DebianJessie;
+ else if (Data.startswith("stretch/sid") || Data[0] == '9')
+ return DebianStretch;
return UnknownDistro;
}
@@ -2794,92 +2987,105 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
/// so we provide a rough mapping here.
static std::string getMultiarchTriple(const llvm::Triple &TargetTriple,
StringRef SysRoot) {
+ llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment();
+
// For most architectures, just use whatever we have rather than trying to be
// clever.
switch (TargetTriple.getArch()) {
default:
- return TargetTriple.str();
+ break;
- // We use the existence of '/lib/<triple>' as a directory to detect some
- // common linux triples that don't quite match the Clang triple for both
- // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
- // regardless of what the actual target triple is.
+ // We use the existence of '/lib/<triple>' as a directory to detect some
+ // common linux triples that don't quite match the Clang triple for both
+ // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+ // regardless of what the actual target triple is.
case llvm::Triple::arm:
case llvm::Triple::thumb:
- if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf"))
return "arm-linux-gnueabihf";
} else {
if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi"))
return "arm-linux-gnueabi";
}
- return TargetTriple.str();
+ break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
return "armeb-linux-gnueabihf";
} else {
if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi"))
return "armeb-linux-gnueabi";
}
- return TargetTriple.str();
+ break;
case llvm::Triple::x86:
if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu"))
return "i386-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::x86_64:
// We don't want this for x32, otherwise it will match x86_64 libs
- if (TargetTriple.getEnvironment() != llvm::Triple::GNUX32 &&
+ if (TargetEnvironment != llvm::Triple::GNUX32 &&
llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu"))
return "x86_64-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::aarch64:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::aarch64_be:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::mips:
if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu"))
return "mips-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::mipsel:
if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu"))
return "mipsel-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::mips64:
if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnu"))
return "mips64-linux-gnu";
if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
return "mips64-linux-gnuabi64";
- return TargetTriple.str();
+ break;
case llvm::Triple::mips64el:
if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnu"))
return "mips64el-linux-gnu";
if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
return "mips64el-linux-gnuabi64";
- return TargetTriple.str();
+ break;
case llvm::Triple::ppc:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu"))
return "powerpc-linux-gnu";
- return TargetTriple.str();
+ break;
case llvm::Triple::ppc64:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu"))
return "powerpc64-linux-gnu";
+ break;
case llvm::Triple::ppc64le:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
return "powerpc64le-linux-gnu";
- return TargetTriple.str();
+ break;
+ case llvm::Triple::sparc:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/sparc-linux-gnu"))
+ return "sparc-linux-gnu";
+ break;
+ case llvm::Triple::sparcv9:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/sparc64-linux-gnu"))
+ return "sparc64-linux-gnu";
+ break;
}
+ return TargetTriple.str();
}
static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
- if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
+ if (llvm::sys::fs::exists(Path))
+ Paths.push_back(Path.str());
}
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
@@ -2913,7 +3119,7 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
}
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+ : Generic_ELF(D, Triple, Args) {
GCCInstallation.init(D, Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
llvm::Triple::ArchType Arch = Triple.getArch();
@@ -2929,7 +3135,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// FIXME: This seems unlikely to be Linux-specific.
ToolChain::path_list &PPaths = getProgramPaths();
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
- GCCInstallation.getTriple().str() + "/bin").str());
+ GCCInstallation.getTriple().str() + "/bin")
+ .str());
Linker = GetLinkerPath();
@@ -2967,8 +3174,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (IsRedhat(Distro))
ExtraOpts.push_back("--no-add-needed");
- if (Distro == DebianSqueeze || Distro == DebianWheezy ||
- Distro == DebianJessie || IsOpenSUSE(Distro) ||
+ if ((IsDebian(Distro) && Distro >= DebianSqueeze) || IsOpenSUSE(Distro) ||
(IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) ||
(IsUbuntu(Distro) && Distro >= UbuntuKarmic))
ExtraOpts.push_back("--build-id");
@@ -2994,8 +3200,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
- addPathIfExists((GCCInstallation.getInstallPath() +
- Multilib.gccSuffix()),
+ addPathIfExists((GCCInstallation.getInstallPath() + Multilib.gccSuffix()),
Paths);
// GCC cross compiling toolchains will install target libraries which ship
@@ -3017,7 +3222,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Note that this matches the GCC behavior. See the below comment for where
// Clang diverges from GCC's behavior.
addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
- Multilib.osSuffix(),
+ Multilib.osSuffix(),
Paths);
// If the GCC installation we found is inside of the sysroot, we want to
@@ -3054,13 +3259,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// installations with strange symlinks.
if (GCCInstallation.isValid()) {
addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
- "/../../" + OSLibDir, Paths);
+ "/../../" + OSLibDir,
+ Paths);
// Add the 'other' biarch variant path
Multilib BiarchSibling;
if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
- addPathIfExists(GCCInstallation.getInstallPath() +
- BiarchSibling.gccSuffix(), Paths);
+ addPathIfExists(
+ GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(), Paths);
}
// See comments above on the multilib variant for details of why this is
@@ -3068,8 +3274,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const std::string &LibPath = GCCInstallation.getParentLibPath();
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const Multilib &Multilib = GCCInstallation.getMultilib();
- addPathIfExists(LibPath + "/../" + GCCTriple.str() +
- "/lib" + Multilib.osSuffix(), Paths);
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib" +
+ Multilib.osSuffix(),
+ Paths);
// See comments above on the multilib variant for details of why this is
// only included from within the sysroot.
@@ -3089,16 +3296,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(SysRoot + "/usr/lib", Paths);
}
-bool Linux::HasNativeLLVMSupport() const {
- return true;
-}
+bool Linux::HasNativeLLVMSupport() const { return true; }
-Tool *Linux::buildLinker() const {
- return new tools::gnutools::Link(*this);
-}
+Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); }
Tool *Linux::buildAssembler() const {
- return new tools::gnutools::Assemble(*this);
+ return new tools::gnutools::Assembler(*this);
}
std::string Linux::computeSysRoot() const {
@@ -3116,8 +3319,9 @@ std::string Linux::computeSysRoot() const {
const StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" +
- Multilib.osSuffix()).str();
+ std::string Path =
+ (InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix())
+ .str();
if (llvm::sys::fs::exists(Path))
return Path;
@@ -3144,7 +3348,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ addSystemInclude(DriverArgs, CC1Args, P);
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@@ -3168,7 +3372,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Add include directories specific to the selected multilib set and multilib.
if (GCCInstallation.isValid()) {
- auto Callback = Multilibs.includeDirsCallback();
+ const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
const auto IncludePaths = Callback(GCCInstallation.getInstallPath(),
GCCInstallation.getTriple().str(),
@@ -3180,81 +3384,91 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Implement generic Debian multiarch support.
const StringRef X86_64MultiarchIncludeDirs[] = {
- "/usr/include/x86_64-linux-gnu",
+ "/usr/include/x86_64-linux-gnu",
- // FIXME: These are older forms of multiarch. It's not clear that they're
- // in use in any released version of Debian, so we should consider
- // removing them.
- "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"
- };
+ // FIXME: These are older forms of multiarch. It's not clear that they're
+ // in use in any released version of Debian, so we should consider
+ // removing them.
+ "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"};
const StringRef X86MultiarchIncludeDirs[] = {
- "/usr/include/i386-linux-gnu",
+ "/usr/include/i386-linux-gnu",
- // FIXME: These are older forms of multiarch. It's not clear that they're
- // in use in any released version of Debian, so we should consider
- // removing them.
- "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
- "/usr/include/i486-linux-gnu"
- };
+ // FIXME: These are older forms of multiarch. It's not clear that they're
+ // in use in any released version of Debian, so we should consider
+ // removing them.
+ "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
+ "/usr/include/i486-linux-gnu"};
const StringRef AArch64MultiarchIncludeDirs[] = {
- "/usr/include/aarch64-linux-gnu"
- };
+ "/usr/include/aarch64-linux-gnu"};
const StringRef ARMMultiarchIncludeDirs[] = {
- "/usr/include/arm-linux-gnueabi"
- };
+ "/usr/include/arm-linux-gnueabi"};
const StringRef ARMHFMultiarchIncludeDirs[] = {
- "/usr/include/arm-linux-gnueabihf"
- };
- const StringRef MIPSMultiarchIncludeDirs[] = {
- "/usr/include/mips-linux-gnu"
- };
+ "/usr/include/arm-linux-gnueabihf"};
+ const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"};
const StringRef MIPSELMultiarchIncludeDirs[] = {
- "/usr/include/mipsel-linux-gnu"
- };
+ "/usr/include/mipsel-linux-gnu"};
const StringRef MIPS64MultiarchIncludeDirs[] = {
- "/usr/include/mips64-linux-gnu",
- "/usr/include/mips64-linux-gnuabi64"
- };
+ "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"};
const StringRef MIPS64ELMultiarchIncludeDirs[] = {
- "/usr/include/mips64el-linux-gnu",
- "/usr/include/mips64el-linux-gnuabi64"
- };
+ "/usr/include/mips64el-linux-gnu",
+ "/usr/include/mips64el-linux-gnuabi64"};
const StringRef PPCMultiarchIncludeDirs[] = {
- "/usr/include/powerpc-linux-gnu"
- };
+ "/usr/include/powerpc-linux-gnu"};
const StringRef PPC64MultiarchIncludeDirs[] = {
- "/usr/include/powerpc64-linux-gnu"
- };
+ "/usr/include/powerpc64-linux-gnu"};
const StringRef PPC64LEMultiarchIncludeDirs[] = {
- "/usr/include/powerpc64le-linux-gnu"
- };
+ "/usr/include/powerpc64le-linux-gnu"};
+ const StringRef SparcMultiarchIncludeDirs[] = {
+ "/usr/include/sparc-linux-gnu"};
+ const StringRef Sparc64MultiarchIncludeDirs[] = {
+ "/usr/include/sparc64-linux-gnu"};
ArrayRef<StringRef> MultiarchIncludeDirs;
- if (getTriple().getArch() == llvm::Triple::x86_64) {
+ switch (getTriple().getArch()) {
+ case llvm::Triple::x86_64:
MultiarchIncludeDirs = X86_64MultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::x86) {
+ break;
+ case llvm::Triple::x86:
MultiarchIncludeDirs = X86MultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::aarch64_be) {
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::arm) {
+ break;
+ case llvm::Triple::arm:
if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
else
MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::mips) {
+ break;
+ case llvm::Triple::mips:
MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::mipsel) {
+ break;
+ case llvm::Triple::mipsel:
MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::mips64) {
+ break;
+ case llvm::Triple::mips64:
MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::mips64el) {
+ break;
+ case llvm::Triple::mips64el:
MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::ppc) {
+ break;
+ case llvm::Triple::ppc:
MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::ppc64) {
+ break;
+ case llvm::Triple::ppc64:
MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
- } else if (getTriple().getArch() == llvm::Triple::ppc64le) {
+ break;
+ case llvm::Triple::ppc64le:
MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs;
+ break;
+ case llvm::Triple::sparc:
+ MultiarchIncludeDirs = SparcMultiarchIncludeDirs;
+ break;
+ case llvm::Triple::sparcv9:
+ MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs;
+ break;
+ default:
+ break;
}
for (StringRef Dir : MultiarchIncludeDirs) {
if (llvm::sys::fs::exists(SysRoot + Dir)) {
@@ -3275,13 +3489,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
}
/// \brief Helper to add the variant paths of a libstdc++ installation.
-/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
- StringRef GCCTriple,
- StringRef GCCMultiarchTriple,
- StringRef TargetMultiarchTriple,
- Twine IncludeSuffix,
- const ArgList &DriverArgs,
- ArgStringList &CC1Args) {
+/*static*/ bool Linux::addLibStdCXXIncludePaths(
+ Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
+ StringRef TargetMultiarchTriple, Twine IncludeSuffix,
+ const ArgList &DriverArgs, ArgStringList &CC1Args) {
if (!llvm::sys::fs::exists(Base + Suffix))
return false;
@@ -3319,15 +3530,15 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// Check if libc++ has been enabled and provide its include paths if so.
if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
const std::string LibCXXIncludePathCandidates[] = {
- // The primary location is within the Clang installation.
- // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
- // newer ABI versions.
- getDriver().Dir + "/../include/c++/v1",
-
- // We also check the system as for a long time this is the only place Clang looked.
- // FIXME: We should really remove this. It doesn't make any sense.
- getDriver().SysRoot + "/usr/include/c++/v1"
- };
+ // The primary location is within the Clang installation.
+ // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
+ // newer ABI versions.
+ getDriver().Dir + "/../include/c++/v1",
+
+ // We also check the system as for a long time this is the only place
+ // Clang looked.
+ // FIXME: We should really remove this. It doesn't make any sense.
+ getDriver().SysRoot + "/usr/include/c++/v1"};
for (const auto &IncludePath : LibCXXIncludePathCandidates) {
if (!llvm::sys::fs::exists(IncludePath))
continue;
@@ -3358,24 +3569,24 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// The primary search for libstdc++ supports multiarch variants.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
- "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple,
- TargetMultiarchTriple,
+ "/c++/" + Version.Text, TripleStr,
+ GCCMultiarchTriple, TargetMultiarchTriple,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return;
// Otherwise, fall back on a bunch of options which don't use multiarch
// layouts for simplicity.
const std::string LibStdCXXIncludePathCandidates[] = {
- // Gentoo is weird and places its headers inside the GCC install, so if the
- // first attempt to find the headers fails, try these patterns.
- InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
- Version.MinorStr,
- InstallDir.str() + "/include/g++-v" + Version.MajorStr,
- // Android standalone toolchain has C++ headers in yet another place.
- LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
- // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
- // without a subdirectory corresponding to the gcc version.
- LibDir.str() + "/../include/c++",
+ // Gentoo is weird and places its headers inside the GCC install,
+ // so if the first attempt to find the headers fails, try these patterns.
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
+ Version.MinorStr,
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr,
+ // Android standalone toolchain has C++ headers in yet another place.
+ LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+ // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
+ // without a subdirectory corresponding to the gcc version.
+ LibDir.str() + "/../include/c++",
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
@@ -3387,14 +3598,38 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-bool Linux::isPIEDefault() const {
- return getSanitizerArgs().requiresPIE();
+bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
+
+SanitizerMask Linux::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+ const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el;
+ const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 ||
+ getTriple().getArch() == llvm::Triple::ppc64le;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::Vptr;
+ if (IsX86_64 || IsMIPS64) {
+ Res |= SanitizerKind::DataFlow;
+ Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::Thread;
+ }
+ if (IsX86_64 || IsMIPS64 || IsPowerPC64)
+ Res |= SanitizerKind::Memory;
+ if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::Function;
+ Res |= SanitizerKind::SafeStack;
+ }
+ return Res;
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
-DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
+DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
// Path mangling to find libexec
getProgramPaths().push_back(getDriver().getInstalledDir());
@@ -3410,47 +3645,93 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList
}
Tool *DragonFly::buildAssembler() const {
- return new tools::dragonfly::Assemble(*this);
+ return new tools::dragonfly::Assembler(*this);
}
Tool *DragonFly::buildLinker() const {
- return new tools::dragonfly::Link(*this);
+ 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) {
+XCore::XCore(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
// ProgramPaths are found via 'PATH' environment variable.
}
Tool *XCore::buildAssembler() const {
- return new tools::XCore::Assemble(*this);
+ return new tools::XCore::Assembler(*this);
}
-Tool *XCore::buildLinker() const {
- return new tools::XCore::Link(*this);
-}
+Tool *XCore::buildLinker() const { return new tools::XCore::Linker(*this); }
-bool XCore::isPICDefault() const {
- return false;
-}
+bool XCore::isPICDefault() const { return false; }
-bool XCore::isPIEDefault() const {
- return false;
-}
+bool XCore::isPIEDefault() const { return false; }
-bool XCore::isPICDefaultForced() const {
- return false;
-}
+bool XCore::isPICDefaultForced() const { return false; }
-bool XCore::SupportsProfiling() const {
- return false;
-}
+bool XCore::SupportsProfiling() const { return false; }
-bool XCore::hasBlocksRuntime() const {
- return false;
-}
+bool XCore::hasBlocksRuntime() const { return false; }
void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
@@ -3459,15 +3740,15 @@ void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
if (const char *cl_include_dir = getenv("XCC_C_INCLUDE_PATH")) {
SmallVector<StringRef, 4> Dirs;
- const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
ArrayRef<StringRef> DirVec(Dirs);
addSystemIncludes(DriverArgs, CC1Args, DirVec);
}
}
-void XCore::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
+void XCore::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
CC1Args.push_back("-nostdsysteminc");
}
@@ -3479,7 +3760,7 @@ void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
return;
if (const char *cl_include_dir = getenv("XCC_CPLUS_INCLUDE_PATH")) {
SmallVector<StringRef, 4> Dirs;
- const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
ArrayRef<StringRef> DirVec(Dirs);
addSystemIncludes(DriverArgs, CC1Args, DirVec);
@@ -3490,3 +3771,46 @@ void XCore::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// We don't output any lib args. This is handled by xcc.
}
+
+// SHAVEToolChain does not call Clang's C compiler.
+// We override SelectTool to avoid testing ShouldUseClangCompiler().
+Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const {
+ switch (JA.getKind()) {
+ case Action::CompileJobClass:
+ if (!Compiler)
+ Compiler.reset(new tools::SHAVE::Compiler(*this));
+ return Compiler.get();
+ case Action::AssembleJobClass:
+ if (!Assembler)
+ Assembler.reset(new tools::SHAVE::Assembler(*this));
+ return Assembler.get();
+ default:
+ return ToolChain::getTool(JA.getKind());
+ }
+}
+
+SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {}
+
+SHAVEToolChain::~SHAVEToolChain() {}
+
+/// Following are methods necessary to avoid having moviClang be an abstract
+/// class.
+
+Tool *SHAVEToolChain::getTool(Action::ActionClass AC) const {
+ // SelectTool() must find a tool using the method in the superclass.
+ // There's nothing we can do if that fails.
+ llvm_unreachable("SHAVEToolChain can't getTool");
+}
+
+Tool *SHAVEToolChain::buildLinker() const {
+ // SHAVEToolChain executables can not be linked except by the vendor tools.
+ llvm_unreachable("SHAVEToolChain can't buildLinker");
+}
+
+Tool *SHAVEToolChain::buildAssembler() const {
+ // This one you'd think should be reachable since we expose an
+ // assembler to the driver, except not the way it expects.
+ llvm_unreachable("SHAVEToolChain can't buildAssembler");
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
index 47fb10d..327ff9b 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
@@ -101,7 +101,7 @@ protected:
public:
GCCInstallationDetector() : IsValid(false) {}
void init(const Driver &D, const llvm::Triple &TargetTriple,
- const llvm::opt::ArgList &Args);
+ const llvm::opt::ArgList &Args);
/// \brief Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
@@ -152,7 +152,7 @@ protected:
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Generic_GCC();
+ ~Generic_GCC() override;
void printVerboseInfo(raw_ostream &OS) const override;
@@ -179,8 +179,8 @@ protected:
/// @}
private:
- mutable std::unique_ptr<tools::gcc::Preprocess> Preprocess;
- mutable std::unique_ptr<tools::gcc::Compile> Compile;
+ mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocess;
+ mutable std::unique_ptr<tools::gcc::Compiler> Compile;
};
class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
@@ -188,6 +188,7 @@ protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
Tool *getTool(Action::ActionClass AC) const override;
+
private:
mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
@@ -195,8 +196,8 @@ private:
public:
MachO(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
- ~MachO();
+ const llvm::opt::ArgList &Args);
+ ~MachO() override;
/// @name MachO specific toolchain API
/// {
@@ -205,7 +206,6 @@ public:
/// example, Apple treats different ARM variations as distinct architectures.
StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
-
/// Add the linker arguments to link the ARC runtime library.
virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {}
@@ -214,30 +214,31 @@ public:
virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- virtual void
- addStartObjectFileArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {}
+ virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ }
virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {}
/// On some iOS platforms, kernel and kernel modules were built statically. Is
/// this such a target?
- virtual bool isKernelStatic() const {
- return false;
- }
+ virtual bool isKernelStatic() const { return false; }
/// Is the target either iOS or an iOS simulator?
- bool isTargetIOSBased() const {
- return false;
- }
+ bool isTargetIOSBased() const { return false; }
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- StringRef DarwinLibName,
- bool AlwaysLink = false,
- bool IsEmbedded = false,
- bool AddRPath = false) const;
+ StringRef DarwinLibName, bool AlwaysLink = false,
+ bool IsEmbedded = false, bool AddRPath = false) const;
+
+ /// Add any profiling runtime libraries that are needed. This is essentially a
+ /// MachO specific version of addProfileRT in Tools.cpp.
+ virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ // There aren't any profiling libs for embedded targets currently.
+ }
/// }
/// @name ToolChain Implementation
@@ -264,22 +265,16 @@ public:
return true;
}
- bool IsMathErrnoDefault() const override {
- return false;
- }
+ bool IsMathErrnoDefault() const override { return false; }
- bool IsEncodeExtendedBlockSignatureDefault() const override {
- return true;
- }
+ bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }
bool IsObjCNonFragileABIDefault() const override {
// Non-fragile ABI is default for everything but i386.
return getTriple().getArch() != llvm::Triple::x86;
}
- bool UseObjCMixedDispatch() const override {
- return true;
- }
+ bool UseObjCMixedDispatch() const override { return true; }
bool IsUnwindTablesDefault() const override;
@@ -293,25 +288,18 @@ public:
bool SupportsProfiling() const override;
- bool SupportsObjCGC() const override {
- return false;
- }
+ bool SupportsObjCGC() const override { return false; }
bool UseDwarfDebugFlags() const override;
- bool UseSjLjExceptions() const override {
- return false;
- }
+ bool UseSjLjExceptions() const override { return false; }
/// }
};
- /// Darwin - The base Darwin tool chain.
+/// Darwin - The base Darwin tool chain.
class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
public:
- /// The host version.
- unsigned DarwinVersion[3];
-
/// Whether the information on the target has been initialized.
//
// FIXME: This should be eliminated. What we want to do is make this part of
@@ -319,11 +307,7 @@ public:
// the argument translation business.
mutable bool TargetInitialized;
- enum DarwinPlatformKind {
- MacOS,
- IPhoneOS,
- IPhoneOSSimulator
- };
+ enum DarwinPlatformKind { MacOS, IPhoneOS, IPhoneOSSimulator };
mutable DarwinPlatformKind TargetPlatform;
@@ -331,21 +315,12 @@ public:
mutable VersionTuple TargetVersion;
private:
- /// The default macosx-version-min of this tool chain; empty until
- /// initialized.
- std::string MacosxVersionMin;
-
- /// The default ios-version-min of this tool chain; empty until
- /// initialized.
- std::string iOSVersionMin;
-
-private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
public:
Darwin(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Darwin();
+ ~Darwin() override;
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
@@ -353,19 +328,19 @@ public:
/// @name Apple Specific Toolchain Implementation
/// {
- void
- addMinVersionArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
-
- void
- addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ void addMinVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
bool isKernelStatic() const override {
- return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0) ||
- getTriple().getArch() == llvm::Triple::aarch64;
+ return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0);
}
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
protected:
/// }
/// @name Darwin specific Toolchain functions
@@ -403,6 +378,7 @@ protected:
}
bool isTargetMacOS() const {
+ assert(TargetInitialized && "Target not initialized!");
return TargetPlatform == MacOS;
}
@@ -413,12 +389,13 @@ protected:
return TargetVersion;
}
- bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
+ unsigned V2 = 0) const {
assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
return TargetVersion < VersionTuple(V0, V1, V2);
}
- bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
assert(isTargetMacOS() && "Unexpected call for non OS X target!");
return TargetVersion < VersionTuple(V0, V1, V2);
}
@@ -465,6 +442,8 @@ public:
void CheckObjCARC() const override;
bool UseSjLjExceptions() const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
};
/// DarwinClang - The Darwin toolchain used by Clang.
@@ -476,29 +455,30 @@ public:
/// @name Apple ToolChain Implementation
/// {
- void
- AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
- void
- AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
- void
- AddCCKextLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
- virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args)
- const override;
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddLinkARCArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddLinkARCArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
/// }
+
+private:
+ void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ StringRef Sanitizer) const;
};
class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
virtual void anchor();
+
public:
Generic_ELF(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
@@ -508,18 +488,75 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
};
+class LLVM_LIBRARY_VISIBILITY CloudABI : public Generic_ELF {
+public:
+ CloudABI(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ bool HasNativeLLVMSupport() const override { return true; }
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
+ return ToolChain::CST_Libcxx;
+ }
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ bool isPIEDefault() const override { return false; }
+
+protected:
+ Tool *buildLinker() const override;
+};
+
class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
public:
Solaris(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
bool IsIntegratedAssemblerDefault() const override { return true; }
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
-
};
+class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
+public:
+ MinGW(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsIntegratedAssemblerDefault() const override;
+ bool IsUnwindTablesDefault() const override;
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+ bool UseSEHExceptions() const;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+ Tool *getTool(Action::ActionClass AC) const override;
+ Tool *buildLinker() const override;
+ Tool *buildAssembler() const override;
+
+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;
+};
class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
public:
@@ -548,13 +585,13 @@ public:
bool IsObjCNonFragileABIDefault() const override { return true; }
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
- return 1;
+ return 1;
}
protected:
@@ -572,12 +609,14 @@ public:
bool IsObjCNonFragileABIDefault() const override { return true; }
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool UseSjLjExceptions() const override;
bool isPIEDefault() const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
@@ -593,12 +632,10 @@ public:
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- bool IsUnwindTablesDefault() const override {
- return true;
- }
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ bool IsUnwindTablesDefault() const override { return true; }
protected:
Tool *buildAssembler() const override;
@@ -637,10 +674,11 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool isPIEDefault() const override;
+ SanitizerMask getSupportedSanitizers() const override;
std::string Linker;
std::vector<std::string> ExtraOpts;
@@ -661,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;
@@ -670,14 +720,14 @@ protected:
public:
Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~Hexagon_TC();
+ ~Hexagon_TC() override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
@@ -686,6 +736,48 @@ public:
const llvm::opt::ArgList &Args);
static StringRef GetTargetCPU(const llvm::opt::ArgList &Args);
+
+ static const char *GetSmallDataThreshold(const llvm::opt::ArgList &Args);
+
+ static bool UsesG0(const char *smallDataThreshold);
+};
+
+class LLVM_LIBRARY_VISIBILITY NaCl_TC : public Generic_ELF {
+public:
+ NaCl_TC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ 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
+ // and the toolchain outlives all the jobs.
+ const char *GetNaClArmMacrosPath() const { return NaClArmMacrosPath.c_str(); }
+
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+ std::string Linker;
+
+protected:
+ Tool *buildLinker() const override;
+ Tool *buildAssembler() const override;
+
+private:
+ std::string NaClArmMacrosPath;
};
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
@@ -694,7 +786,7 @@ class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
public:
TCEToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- ~TCEToolChain();
+ ~TCEToolChain() override;
bool IsMathErrnoDefault() const override;
bool isPICDefault() const override;
@@ -716,9 +808,9 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool getWindowsSDKDir(std::string &path, int &major, int &minor) const;
bool getWindowsSDKLibraryPath(std::string &path) const;
@@ -726,6 +818,10 @@ public:
bool getVisualStudioBinariesFolder(const char *clangProgramPath,
std::string &path) const;
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
@@ -751,12 +847,12 @@ public:
return 0;
}
- void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args)
- const override;
- void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args)
- const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
@@ -768,26 +864,51 @@ protected:
class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain {
public:
XCore(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ const llvm::opt::ArgList &Args);
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+
public:
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
bool SupportsProfiling() const override;
bool hasBlocksRuntime() const override;
- void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
};
+/// SHAVEToolChain - A tool chain using the compiler installed by the the
+// Movidius SDK into MV_TOOLS_DIR (which we assume will be copied to llvm's
+// installation dir) to perform all subcommands.
+class LLVM_LIBRARY_VISIBILITY SHAVEToolChain : public Generic_GCC {
+public:
+ SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~SHAVEToolChain() override;
+
+ virtual Tool *SelectTool(const JobAction &JA) const override;
+
+protected:
+ Tool *getTool(Action::ActionClass AC) const override;
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+private:
+ mutable std::unique_ptr<Tool> Compiler;
+ mutable std::unique_ptr<Tool> Assembler;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 5161ddf..9f41137 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -10,6 +10,7 @@
#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
@@ -23,6 +24,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -30,16 +32,20 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/TargetParser.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
+#ifdef LLVM_ON_UNIX
+#include <unistd.h> // For getuid().
+#endif
+
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
@@ -78,10 +84,10 @@ static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
// In gcc, only ARM checks this, but it seems reasonable to check universally.
if (Args.hasArg(options::OPT_static))
- if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
- options::OPT_mdynamic_no_pic))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-static";
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic))
+ D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
+ << "-static";
}
// Add backslashes to escape spaces and other backslashes.
@@ -89,9 +95,10 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
// the -dwarf-debug-flags option.
static void EscapeSpacesAndBackslashes(const char *Arg,
SmallVectorImpl<char> &Res) {
- for ( ; *Arg; ++Arg) {
+ for (; *Arg; ++Arg) {
switch (*Arg) {
- default: break;
+ default:
+ break;
case ' ':
case '\\':
Res.push_back('\\');
@@ -103,8 +110,7 @@ static void EscapeSpacesAndBackslashes(const char *Arg,
// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
-static void QuoteTarget(StringRef Target,
- SmallVectorImpl<char> &Res) {
+static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
for (unsigned i = 0, e = Target.size(); i != e; ++i) {
switch (Target[i]) {
case ' ':
@@ -130,10 +136,8 @@ static void QuoteTarget(StringRef Target,
}
}
-static void addDirectoryList(const ArgList &Args,
- ArgStringList &CmdArgs,
- const char *ArgName,
- const char *EnvVar) {
+static void addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
+ const char *ArgName, const char *EnvVar) {
const char *DirList = ::getenv(EnvVar);
bool CombinedArg = false;
@@ -159,7 +163,8 @@ static void addDirectoryList(const ArgList &Args,
}
} else {
if (CombinedArg) {
- CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
} else {
CmdArgs.push_back(ArgName);
CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
@@ -185,9 +190,8 @@ static void addDirectoryList(const ArgList &Args,
}
}
-static void AddLinkerInputs(const ToolChain &TC,
- const InputInfoList &Inputs, const ArgList &Args,
- ArgStringList &CmdArgs) {
+static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
+ const ArgList &Args, ArgStringList &CmdArgs) {
const Driver &D = TC.getDriver();
// Add extra linker input arguments which are not treated as inputs
@@ -199,10 +203,8 @@ static void AddLinkerInputs(const ToolChain &TC,
// Don't try to pass LLVM inputs unless we have native support.
if (II.getType() == types::TY_LLVM_IR ||
II.getType() == types::TY_LTO_IR ||
- II.getType() == types::TY_LLVM_BC ||
- II.getType() == types::TY_LTO_BC)
- D.Diag(diag::err_drv_no_linker_llvm_support)
- << TC.getTripleString();
+ II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
}
// Add filenames immediately.
@@ -224,7 +226,7 @@ static void AddLinkerInputs(const ToolChain &TC,
A.claim();
A.render(Args, CmdArgs);
} else {
- A.renderAsInput(Args, CmdArgs);
+ A.renderAsInput(Args, CmdArgs);
}
}
@@ -253,14 +255,11 @@ static bool forwardToGCC(const Option &O) {
// Don't forward inputs from the original command line. They are added from
// InputInfoList.
return O.getKind() != Option::InputClass &&
- !O.hasFlag(options::DriverOption) &&
- !O.hasFlag(options::LinkerInput);
+ !O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);
}
-void Clang::AddPreprocessingOptions(Compilation &C,
- const JobAction &JA,
- const Driver &D,
- const ArgList &Args,
+void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
+ const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfo &Output,
const InputInfoList &Inputs) const {
@@ -319,25 +318,24 @@ void Clang::AddPreprocessingOptions(Compilation &C,
if (A->getOption().matches(options::OPT_M) ||
A->getOption().matches(options::OPT_MD))
CmdArgs.push_back("-sys-header-deps");
-
- if (isa<PrecompileJobAction>(JA))
+ if ((isa<PrecompileJobAction>(JA) &&
+ !Args.hasArg(options::OPT_fno_module_file_deps)) ||
+ Args.hasArg(options::OPT_fmodule_file_deps))
CmdArgs.push_back("-module-file-deps");
}
if (Args.hasArg(options::OPT_MG)) {
if (!A || A->getOption().matches(options::OPT_MD) ||
- A->getOption().matches(options::OPT_MMD))
+ A->getOption().matches(options::OPT_MMD))
D.Diag(diag::err_drv_mg_requires_m_or_mm);
CmdArgs.push_back("-MG");
}
Args.AddLastArg(CmdArgs, options::OPT_MP);
+ Args.AddLastArg(CmdArgs, options::OPT_MV);
// Convert all -MQ <target> args to -MT <quoted target>
- for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
- options::OPT_MQ),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) {
A->claim();
if (A->getOption().matches(options::OPT_MQ)) {
@@ -346,7 +344,7 @@ void Clang::AddPreprocessingOptions(Compilation &C,
QuoteTarget(A->getValue(), Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
- // -MT flag - no change
+ // -MT flag - no change
} else {
A->render(Args, CmdArgs);
}
@@ -358,10 +356,7 @@ void Clang::AddPreprocessingOptions(Compilation &C,
// replacement into a build system already set up to be generating
// .gch files.
bool RenderedImplicitInclude = false;
- for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = it;
-
+ for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
if (A->getOption().matches(options::OPT_include)) {
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
@@ -377,19 +372,19 @@ void Clang::AddPreprocessingOptions(Compilation &C,
P += ".dummy";
if (UsePCH) {
llvm::sys::path::replace_extension(P, "pch");
- if (llvm::sys::fs::exists(P.str()))
+ if (llvm::sys::fs::exists(P))
FoundPCH = true;
}
if (!FoundPCH) {
llvm::sys::path::replace_extension(P, "pth");
- if (llvm::sys::fs::exists(P.str()))
+ if (llvm::sys::fs::exists(P))
FoundPTH = true;
}
if (!FoundPCH && !FoundPTH) {
llvm::sys::path::replace_extension(P, "gch");
- if (llvm::sys::fs::exists(P.str())) {
+ if (llvm::sys::fs::exists(P)) {
FoundPCH = UsePCH;
FoundPTH = !UsePCH;
}
@@ -402,12 +397,12 @@ void Clang::AddPreprocessingOptions(Compilation &C,
CmdArgs.push_back("-include-pch");
else
CmdArgs.push_back("-include-pth");
- CmdArgs.push_back(Args.MakeArgString(P.str()));
+ CmdArgs.push_back(Args.MakeArgString(P));
continue;
} else {
// Ignore the PCH if not first on command line and emit warning.
- D.Diag(diag::warn_drv_pch_not_first_include)
- << P.str() << A->getAsString(Args);
+ D.Diag(diag::warn_drv_pch_not_first_include) << P
+ << A->getAsString(Args);
}
}
}
@@ -489,6 +484,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return true;
return false;
+ case llvm::Triple::hexagon:
case llvm::Triple::ppc64le:
case llvm::Triple::systemz:
case llvm::Triple::xcore:
@@ -508,8 +504,8 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
// Handle -mhwdiv=.
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
- const ArgList &Args,
- std::vector<const char *> &Features) {
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
StringRef HWDiv = A->getValue();
if (HWDiv == "arm") {
Features.push_back("+hwdiv-arm");
@@ -528,93 +524,34 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A,
}
// Handle -mfpu=.
-//
-// FIXME: Centralize feature selection, defaulting shouldn't be also in the
-// frontend target.
static void getARMFPUFeatures(const Driver &D, const Arg *A,
const ArgList &Args,
std::vector<const char *> &Features) {
StringRef FPU = A->getValue();
-
- // Set the target features based on the FPU.
- if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
- // Disable any default FPU support.
- Features.push_back("-vfp2");
- Features.push_back("-vfp3");
- Features.push_back("-neon");
- } else if (FPU == "vfp") {
- Features.push_back("+vfp2");
- Features.push_back("-neon");
- } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
- Features.push_back("+vfp3");
- Features.push_back("+d16");
- Features.push_back("-neon");
- } else if (FPU == "vfp3" || FPU == "vfpv3") {
- Features.push_back("+vfp3");
- Features.push_back("-neon");
- } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
- Features.push_back("+vfp4");
- Features.push_back("+d16");
- Features.push_back("-neon");
- } else if (FPU == "vfp4" || FPU == "vfpv4") {
- Features.push_back("+vfp4");
- Features.push_back("-neon");
- } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
- Features.push_back("+vfp4");
- Features.push_back("+d16");
- Features.push_back("+fp-only-sp");
- Features.push_back("-neon");
- } else if (FPU == "fp5-sp-d16" || FPU == "fpv5-sp-d16") {
- Features.push_back("+fp-armv8");
- Features.push_back("+fp-only-sp");
- Features.push_back("+d16");
- Features.push_back("-neon");
- Features.push_back("-crypto");
- } else if (FPU == "fp5-dp-d16" || FPU == "fpv5-dp-d16" ||
- FPU == "fp5-d16" || FPU == "fpv5-d16") {
- Features.push_back("+fp-armv8");
- Features.push_back("+d16");
- Features.push_back("-neon");
- Features.push_back("-crypto");
- } else if (FPU == "fp-armv8") {
- Features.push_back("+fp-armv8");
- Features.push_back("-neon");
- Features.push_back("-crypto");
- } else if (FPU == "neon-fp-armv8") {
- Features.push_back("+fp-armv8");
- Features.push_back("+neon");
- Features.push_back("-crypto");
- } else if (FPU == "crypto-neon-fp-armv8") {
- Features.push_back("+fp-armv8");
- Features.push_back("+neon");
- Features.push_back("+crypto");
- } else if (FPU == "neon") {
- Features.push_back("+neon");
- } else if (FPU == "neon-vfpv3") {
- Features.push_back("+vfp3");
- Features.push_back("+neon");
- } else if (FPU == "neon-vfpv4") {
- Features.push_back("+neon");
- Features.push_back("+vfp4");
- } else if (FPU == "none") {
- Features.push_back("-vfp2");
- Features.push_back("-vfp3");
- Features.push_back("-vfp4");
- Features.push_back("-fp-armv8");
- Features.push_back("-crypto");
- Features.push_back("-neon");
- } else
+ unsigned FPUID = llvm::ARMTargetParser::parseFPU(FPU);
+ if (!llvm::ARMTargetParser::getFPUFeatures(FPUID, Features))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
+static int getARMSubArchVersionNumber(const llvm::Triple &Triple) {
+ llvm::StringRef Arch = Triple.getArchName();
+ return llvm::ARMTargetParser::parseArchVersion(Arch);
+}
+
+static bool isARMMProfile(const llvm::Triple &Triple) {
+ llvm::StringRef Arch = Triple.getArchName();
+ unsigned Profile = llvm::ARMTargetParser::parseArchProfile(Arch);
+ return Profile == llvm::ARM::PK_M;
+}
+
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
const llvm::Triple &Triple) {
StringRef FloatABI;
- if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
- options::OPT_mhard_float,
- options::OPT_mfloat_abi_EQ)) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
if (A->getOption().matches(options::OPT_msoft_float))
FloatABI = "soft";
else if (A->getOption().matches(options::OPT_mhard_float))
@@ -622,8 +559,7 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
else {
FloatABI = A->getValue();
if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
- D.Diag(diag::err_drv_invalid_mfloat_abi)
- << A->getAsString(Args);
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
FloatABI = "soft";
}
}
@@ -637,11 +573,8 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
case llvm::Triple::IOS: {
// Darwin defaults to "softfp" for v6 and v7.
//
- // FIXME: Factor out an ARM class so we can cache the arch somewhere.
- std::string ArchName =
- arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
- if (StringRef(ArchName).startswith("v6") ||
- StringRef(ArchName).startswith("v7"))
+ if (getARMSubArchVersionNumber(Triple) == 6 ||
+ getARMSubArchVersionNumber(Triple) == 7)
FloatABI = "softfp";
else
FloatABI = "soft";
@@ -654,7 +587,7 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
break;
case llvm::Triple::FreeBSD:
- switch(Triple.getEnvironment()) {
+ switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
FloatABI = "hard";
break;
@@ -666,7 +599,7 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
break;
default:
- switch(Triple.getEnvironment()) {
+ switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
FloatABI = "hard";
break;
@@ -681,9 +614,7 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
FloatABI = "softfp";
break;
case llvm::Triple::Android: {
- std::string ArchName =
- arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
- if (StringRef(ArchName).startswith("v7"))
+ if (getARMSubArchVersionNumber(Triple) == 7)
FloatABI = "softfp";
else
FloatABI = "soft";
@@ -707,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
@@ -736,6 +669,25 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
getARMHWDivFeatures(D, A, Args, Features);
+ // Check if -march is valid by checking if it can be canonicalised and parsed.
+ // getARMArch is used here instead of just checking the -march value in order
+ // to handle -march=native correctly.
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ std::string Arch = arm::getARMArch(Args, Triple);
+ if (llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_INVALID)
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ }
+
+ // We do a similar thing with -mcpu, but here things are complicated because
+ // the only function we have to check if a cpu is valid is
+ // getLLVMArchSuffixForARM which also needs an architecture.
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ std::string CPU = arm::getARMTargetCPU(Args, Triple);
+ std::string Arch = arm::getARMArch(Args, Triple);
+ if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0)
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ }
+
// Setting -msoft-float effectively disables NEON because of the GCC
// implementation, although the same isn't true of VFP or VFP3.
if (FloatABI == "soft") {
@@ -744,24 +696,36 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("-crypto");
}
- // En/disable crc
- if (Arg *A = Args.getLastArg(options::OPT_mcrc,
- options::OPT_mnocrc)) {
+ // En/disable crc code generation.
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
if (A->getOption().matches(options::OPT_mcrc))
Features.push_back("+crc");
else
Features.push_back("-crc");
}
+
+ 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,
+void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
bool KernelOrKext) const {
const Driver &D = getToolChain().getDriver();
// Get the effective triple, which takes into account the deployment target.
std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
llvm::Triple Triple(TripleStr);
- std::string CPUName = arm::getARMTargetCPU(Args, Triple);
// Select the ABI to use.
//
@@ -774,8 +738,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
- Triple.getOS() == llvm::Triple::UnknownOS ||
- StringRef(CPUName).startswith("cortex-m")) {
+ Triple.getOS() == llvm::Triple::UnknownOS || isARMMProfile(Triple)) {
ABIName = "aapcs";
} else {
ABIName = "apcs-gnu";
@@ -785,7 +748,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
ABIName = "aapcs";
} else {
// Select the default based on the platform.
- switch(Triple.getEnvironment()) {
+ switch (Triple.getEnvironment()) {
case llvm::Triple::Android:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIHF:
@@ -828,11 +791,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// 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");
@@ -856,17 +814,18 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
}
}
- // Setting -mno-global-merge disables the codegen global merge pass. Setting
- // -mglobal-merge has no effect as the pass is enabled by default.
+ // Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
+ CmdArgs.push_back("-backend-option");
if (A->getOption().matches(options::OPT_mno_global_merge))
- CmdArgs.push_back("-mno-global-merge");
+ CmdArgs.push_back("-arm-global-merge=false");
+ else
+ CmdArgs.push_back("-arm-global-merge=true");
}
if (!Args.hasFlag(options::OPT_mimplicit_float,
- options::OPT_mno_implicit_float,
- true))
+ options::OPT_mno_implicit_float, true))
CmdArgs.push_back("-no-implicit-float");
// llvm does not support reserving registers in general. There is support
@@ -888,7 +847,7 @@ static std::string getAArch64TargetCPU(const ArgList &Args) {
CPU = A->getValue();
} else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
StringRef Mcpu = A->getValue();
- CPU = Mcpu.split("+").first;
+ CPU = Mcpu.split("+").first.lower();
}
// Handle CPU name is 'native'.
@@ -952,12 +911,14 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
}
- // Setting -mno-global-merge disables the codegen global merge pass. Setting
- // -mglobal-merge has no effect as the pass is enabled by default.
+ // Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
+ CmdArgs.push_back("-backend-option");
if (A->getOption().matches(options::OPT_mno_global_merge))
- CmdArgs.push_back("-mno-global-merge");
+ CmdArgs.push_back("-aarch64-global-merge=false");
+ else
+ CmdArgs.push_back("-aarch64-global-merge=true");
}
if (Args.hasArg(options::OPT_ffixed_x18)) {
@@ -968,10 +929,8 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
-void mips::getMipsCPUAndABI(const ArgList &Args,
- const llvm::Triple &Triple,
- StringRef &CPUName,
- StringRef &ABIName) {
+void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
+ StringRef &CPUName, StringRef &ABIName) {
const char *DefMips32CPU = "mips32r2";
const char *DefMips64CPU = "mips64r2";
@@ -987,8 +946,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args,
if (Triple.getOS() == llvm::Triple::OpenBSD)
DefMips64CPU = "mips3";
- if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
- options::OPT_mcpu_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ))
CPUName = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
@@ -996,9 +954,9 @@ void mips::getMipsCPUAndABI(const ArgList &Args,
// Convert a GNU style Mips ABI name to the name
// accepted by LLVM Mips backend.
ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
- .Case("32", "o32")
- .Case("64", "n64")
- .Default(ABIName);
+ .Case("32", "o32")
+ .Case("64", "n64")
+ .Default(ABIName);
}
// Setup default CPU and ABI names.
@@ -1029,9 +987,9 @@ void mips::getMipsCPUAndABI(const ArgList &Args,
if (CPUName.empty()) {
// Deduce CPU name from ABI name.
CPUName = llvm::StringSwitch<const char *>(ABIName)
- .Cases("o32", "eabi", DefMips32CPU)
- .Cases("n32", "n64", DefMips64CPU)
- .Default("");
+ .Cases("o32", "eabi", DefMips32CPU)
+ .Cases("n32", "n64", DefMips64CPU)
+ .Default("");
}
// FIXME: Warn on inconsistent use of -march and -mabi.
@@ -1040,18 +998,18 @@ void mips::getMipsCPUAndABI(const ArgList &Args,
// Convert ABI name to the GNU tools acceptable variant.
static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
return llvm::StringSwitch<llvm::StringRef>(ABI)
- .Case("o32", "32")
- .Case("n64", "64")
- .Default(ABI);
+ .Case("o32", "32")
+ .Case("n64", "64")
+ .Default(ABI);
}
// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
StringRef FloatABI;
- if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
- options::OPT_mhard_float,
- options::OPT_mfloat_abi_EQ)) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
if (A->getOption().matches(options::OPT_msoft_float))
FloatABI = "soft";
else if (A->getOption().matches(options::OPT_mhard_float))
@@ -1096,17 +1054,6 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
ABIName = getGnuCompatibleMipsABIName(ABIName);
- // Always override the backend's default ABI.
- std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
- .Case("32", "+o32")
- .Case("n32", "+n32")
- .Case("64", "+n64")
- .Case("eabi", "+eabi")
- .Default(("+" + ABIName).str());
- Features.push_back("-o32");
- Features.push_back("-n64");
- Features.push_back(Args.MakeArgString(ABIFeature));
-
AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
options::OPT_mabicalls, "noabicalls");
@@ -1120,11 +1067,21 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
StringRef Val = StringRef(A->getValue());
- if (Val == "2008")
- Features.push_back("+nan2008");
- else if (Val == "legacy")
- Features.push_back("-nan2008");
- else
+ if (Val == "2008") {
+ if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
+ Features.push_back("+nan2008");
+ else {
+ Features.push_back("-nan2008");
+ D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
+ }
+ } else if (Val == "legacy") {
+ if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
+ Features.push_back("-nan2008");
+ else {
+ Features.push_back("+nan2008");
+ D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
+ }
+ } else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
@@ -1153,7 +1110,7 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back(Args.MakeArgString("+nooddspreg"));
} else
Features.push_back(Args.MakeArgString("+fp64"));
- } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
+ } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
Features.push_back(Args.MakeArgString("+fpxx"));
Features.push_back(Args.MakeArgString("+nooddspreg"));
}
@@ -1180,8 +1137,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
- }
- else {
+ } else {
// Floating point operations and argument passing are hard.
assert(FloatABI == "hard" && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
@@ -1233,51 +1189,51 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
}
return llvm::StringSwitch<const char *>(CPUName)
- .Case("common", "generic")
- .Case("440", "440")
- .Case("440fp", "440")
- .Case("450", "450")
- .Case("601", "601")
- .Case("602", "602")
- .Case("603", "603")
- .Case("603e", "603e")
- .Case("603ev", "603ev")
- .Case("604", "604")
- .Case("604e", "604e")
- .Case("620", "620")
- .Case("630", "pwr3")
- .Case("G3", "g3")
- .Case("7400", "7400")
- .Case("G4", "g4")
- .Case("7450", "7450")
- .Case("G4+", "g4+")
- .Case("750", "750")
- .Case("970", "970")
- .Case("G5", "g5")
- .Case("a2", "a2")
- .Case("a2q", "a2q")
- .Case("e500mc", "e500mc")
- .Case("e5500", "e5500")
- .Case("power3", "pwr3")
- .Case("power4", "pwr4")
- .Case("power5", "pwr5")
- .Case("power5x", "pwr5x")
- .Case("power6", "pwr6")
- .Case("power6x", "pwr6x")
- .Case("power7", "pwr7")
- .Case("power8", "pwr8")
- .Case("pwr3", "pwr3")
- .Case("pwr4", "pwr4")
- .Case("pwr5", "pwr5")
- .Case("pwr5x", "pwr5x")
- .Case("pwr6", "pwr6")
- .Case("pwr6x", "pwr6x")
- .Case("pwr7", "pwr7")
- .Case("pwr8", "pwr8")
- .Case("powerpc", "ppc")
- .Case("powerpc64", "ppc64")
- .Case("powerpc64le", "ppc64le")
- .Default("");
+ .Case("common", "generic")
+ .Case("440", "440")
+ .Case("440fp", "440")
+ .Case("450", "450")
+ .Case("601", "601")
+ .Case("602", "602")
+ .Case("603", "603")
+ .Case("603e", "603e")
+ .Case("603ev", "603ev")
+ .Case("604", "604")
+ .Case("604e", "604e")
+ .Case("620", "620")
+ .Case("630", "pwr3")
+ .Case("G3", "g3")
+ .Case("7400", "7400")
+ .Case("G4", "g4")
+ .Case("7450", "7450")
+ .Case("G4+", "g4+")
+ .Case("750", "750")
+ .Case("970", "970")
+ .Case("G5", "g5")
+ .Case("a2", "a2")
+ .Case("a2q", "a2q")
+ .Case("e500mc", "e500mc")
+ .Case("e5500", "e5500")
+ .Case("power3", "pwr3")
+ .Case("power4", "pwr4")
+ .Case("power5", "pwr5")
+ .Case("power5x", "pwr5x")
+ .Case("power6", "pwr6")
+ .Case("power6x", "pwr6x")
+ .Case("power7", "pwr7")
+ .Case("power8", "pwr8")
+ .Case("pwr3", "pwr3")
+ .Case("pwr4", "pwr4")
+ .Case("pwr5", "pwr5")
+ .Case("pwr5x", "pwr5x")
+ .Case("pwr6", "pwr6")
+ .Case("pwr6x", "pwr6x")
+ .Case("pwr7", "pwr7")
+ .Case("pwr8", "pwr8")
+ .Case("powerpc", "ppc")
+ .Case("powerpc64", "ppc64")
+ .Case("powerpc64le", "ppc64le")
+ .Default("");
}
return "";
@@ -1285,11 +1241,9 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
static void getPPCTargetFeatures(const ArgList &Args,
std::vector<const char *> &Features) {
- for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
- ie = Args.filtered_end();
- it != ie; ++it) {
- StringRef Name = (*it)->getOption().getName();
- (*it)->claim();
+ for (const Arg *A : Args.filtered(options::OPT_m_ppc_Features_Group)) {
+ StringRef Name = A->getOption().getName();
+ A->claim();
// Skip over "-m".
assert(Name.startswith("m") && "Invalid feature name.");
@@ -1318,19 +1272,37 @@ 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())
- switch(getToolChain().getArch()) {
- case llvm::Triple::ppc64:
+ if (getToolChain().getTriple().isOSLinux())
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::ppc64: {
+ // When targeting a processor that supports QPX, or if QPX is
+ // specifically enabled, default to using the ABI that supports QPX (so
+ // long as it is not specifically disabled).
+ bool HasQPX = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ HasQPX = A->getValue() == StringRef("a2q");
+ HasQPX = Args.hasFlag(options::OPT_mqpx, options::OPT_mno_qpx, HasQPX);
+ if (HasQPX) {
+ ABIName = "elfv1-qpx";
+ break;
+ }
+
ABIName = "elfv1";
break;
+ }
case llvm::Triple::ppc64le:
ABIName = "elfv2";
break;
default:
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");
@@ -1348,59 +1320,38 @@ static std::string getR600TargetGPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
const char *GPUName = A->getValue();
return llvm::StringSwitch<const char *>(GPUName)
- .Cases("rv630", "rv635", "r600")
- .Cases("rv610", "rv620", "rs780", "rs880")
- .Case("rv740", "rv770")
- .Case("palm", "cedar")
- .Cases("sumo", "sumo2", "sumo")
- .Case("hemlock", "cypress")
- .Case("aruba", "cayman")
- .Default(GPUName);
+ .Cases("rv630", "rv635", "r600")
+ .Cases("rv610", "rv620", "rs780", "rs880")
+ .Case("rv740", "rv770")
+ .Case("palm", "cedar")
+ .Cases("sumo", "sumo2", "sumo")
+ .Case("hemlock", "cypress")
+ .Case("aruba", "cayman")
+ .Default(GPUName);
}
return "";
}
-static void getSparcTargetFeatures(const ArgList &Args,
- std::vector<const char *> &Features) {
- bool SoftFloatABI = true;
- if (Arg *A =
- Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
- if (A->getOption().matches(options::OPT_mhard_float))
- SoftFloatABI = false;
- }
- if (SoftFloatABI)
- Features.push_back("+soft-float");
-}
-
void Clang::AddSparcTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+ ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
+ std::string Triple = getToolChain().ComputeEffectiveClangTriple(Args);
- // Select the float ABI as determined by -msoft-float and -mhard-float.
- StringRef FloatABI;
- if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
- options::OPT_mhard_float)) {
+ bool SoftFloatABI = false;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
if (A->getOption().matches(options::OPT_msoft_float))
- FloatABI = "soft";
- else if (A->getOption().matches(options::OPT_mhard_float))
- FloatABI = "hard";
- }
-
- // If unspecified, choose the default based on the platform.
- if (FloatABI.empty()) {
- // Assume "soft", but warn the user we are guessing.
- FloatABI = "soft";
- D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ SoftFloatABI = true;
}
- if (FloatABI == "soft") {
- // Floating point operations and argument passing are soft.
- //
- // FIXME: This changes CPP defines, we need -target-soft-float.
- CmdArgs.push_back("-msoft-float");
- } else {
- assert(FloatABI == "hard" && "Invalid float abi!");
- CmdArgs.push_back("-mhard-float");
+ // Only the hard-float ABI on Sparc is standardized, and it is the
+ // default. GCC also supports a nonstandard soft-float ABI mode, and
+ // perhaps LLVM should implement that, too. However, since llvm
+ // currently does not support Sparc soft-float, at all, display an
+ // error if it's requested.
+ if (SoftFloatABI) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target) << "-msoft-float"
+ << Triple;
}
}
@@ -1410,6 +1361,24 @@ static const char *getSystemZTargetCPU(const ArgList &Args) {
return "z10";
}
+static void getSystemZTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // -m(no-)htm overrides use of the transactional-execution facility.
+ if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
+ if (A->getOption().matches(options::OPT_mhtm))
+ Features.push_back("+transactional-execution");
+ else
+ Features.push_back("-transactional-execution");
+ }
+ // -m(no-)vx overrides use of the vector facility.
+ if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
+ if (A->getOption().matches(options::OPT_mvx))
+ Features.push_back("+vector");
+ else
+ Features.push_back("-vector");
+ }
+}
+
static const char *getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
@@ -1430,6 +1399,28 @@ static const char *getX86TargetCPU(const ArgList &Args,
return Args.MakeArgString(CPU);
}
+ if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+ // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
+ StringRef Arch = A->getValue();
+ const char *CPU;
+ if (Triple.getArch() == llvm::Triple::x86) {
+ CPU = llvm::StringSwitch<const char *>(Arch)
+ .Case("IA32", "i386")
+ .Case("SSE", "pentium3")
+ .Case("SSE2", "pentium4")
+ .Case("AVX", "sandybridge")
+ .Case("AVX2", "haswell")
+ .Default(nullptr);
+ } else {
+ CPU = llvm::StringSwitch<const char *>(Arch)
+ .Case("AVX", "sandybridge")
+ .Case("AVX2", "haswell")
+ .Default(nullptr);
+ }
+ if (CPU)
+ return CPU;
+ }
+
// Select the default CPU if none was given (or detection failed).
if (Triple.getArch() != llvm::Triple::x86_64 &&
@@ -1445,6 +1436,10 @@ static const char *getX86TargetCPU(const ArgList &Args,
return Is64Bit ? "core2" : "yonah";
}
+ // Set up default CPU name for PS4 compilers.
+ if (Triple.isPS4CPU())
+ return "btver2";
+
// On Android use targets compatible with gcc
if (Triple.getEnvironment() == llvm::Triple::Android)
return Is64Bit ? "x86-64" : "i686";
@@ -1469,7 +1464,7 @@ static const char *getX86TargetCPU(const ArgList &Args,
}
static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
- switch(T.getArch()) {
+ switch (T.getArch()) {
default:
return "";
@@ -1493,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: {
@@ -1512,6 +1513,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
}
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
return A->getValue();
@@ -1539,7 +1541,8 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
CmdArgs.push_back("-plugin");
- std::string Plugin = ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
+ std::string Plugin =
+ ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
CmdArgs.push_back(Args.MakeArgString(Plugin));
// Try to pass driver level flags relevant to LTO code generation down to
@@ -1551,10 +1554,151 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
}
-static void getX86TargetFeatures(const Driver & D,
- const llvm::Triple &Triple,
+/// This is a helper function for validating the optional refinement step
+/// parameter in reciprocal argument strings. Return false if there is an error
+/// parsing the refinement step. Otherwise, return true and set the Position
+/// of the refinement step in the input string.
+static bool getRefinementStep(const StringRef &In, const Driver &D,
+ const Arg &A, size_t &Position) {
+ const char RefinementStepToken = ':';
+ Position = In.find(RefinementStepToken);
+ if (Position != StringRef::npos) {
+ StringRef Option = A.getOption().getName();
+ StringRef RefStep = In.substr(Position + 1);
+ // Allow exactly one numeric character for the additional refinement
+ // step parameter. This is reasonable for all currently-supported
+ // operations and architectures because we would expect that a larger value
+ // of refinement steps would cause the estimate "optimization" to
+ // under-perform the native operation. Also, if the estimate does not
+ // converge quickly, it probably will not ever converge, so further
+ // refinement steps will not produce a better answer.
+ if (RefStep.size() != 1) {
+ D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
+ return false;
+ }
+ char RefStepChar = RefStep[0];
+ if (RefStepChar < '0' || RefStepChar > '9') {
+ D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
+ return false;
+ }
+ }
+ return true;
+}
+
+/// The -mrecip flag requires processing of many optional parameters.
+static void ParseMRecip(const Driver &D, const ArgList &Args,
+ ArgStringList &OutStrings) {
+ StringRef DisabledPrefixIn = "!";
+ StringRef DisabledPrefixOut = "!";
+ StringRef EnabledPrefixOut = "";
+ StringRef Out = "-mrecip=";
+
+ Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+ if (!A)
+ return;
+
+ unsigned NumOptions = A->getNumValues();
+ if (NumOptions == 0) {
+ // No option is the same as "all".
+ OutStrings.push_back(Args.MakeArgString(Out + "all"));
+ return;
+ }
+
+ // Pass through "all", "none", or "default" with an optional refinement step.
+ if (NumOptions == 1) {
+ StringRef Val = A->getValue(0);
+ size_t RefStepLoc;
+ if (!getRefinementStep(Val, D, *A, RefStepLoc))
+ return;
+ StringRef ValBase = Val.slice(0, RefStepLoc);
+ if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
+ OutStrings.push_back(Args.MakeArgString(Out + Val));
+ return;
+ }
+ }
+
+ // Each reciprocal type may be enabled or disabled individually.
+ // Check each input value for validity, concatenate them all back together,
+ // and pass through.
+
+ llvm::StringMap<bool> OptionStrings;
+ OptionStrings.insert(std::make_pair("divd", false));
+ OptionStrings.insert(std::make_pair("divf", false));
+ OptionStrings.insert(std::make_pair("vec-divd", false));
+ OptionStrings.insert(std::make_pair("vec-divf", false));
+ OptionStrings.insert(std::make_pair("sqrtd", false));
+ OptionStrings.insert(std::make_pair("sqrtf", false));
+ OptionStrings.insert(std::make_pair("vec-sqrtd", false));
+ OptionStrings.insert(std::make_pair("vec-sqrtf", false));
+
+ for (unsigned i = 0; i != NumOptions; ++i) {
+ StringRef Val = A->getValue(i);
+
+ bool IsDisabled = Val.startswith(DisabledPrefixIn);
+ // Ignore the disablement token for string matching.
+ if (IsDisabled)
+ Val = Val.substr(1);
+
+ size_t RefStep;
+ if (!getRefinementStep(Val, D, *A, RefStep))
+ return;
+
+ StringRef ValBase = Val.slice(0, RefStep);
+ llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
+ if (OptionIter == OptionStrings.end()) {
+ // Try again specifying float suffix.
+ OptionIter = OptionStrings.find(ValBase.str() + 'f');
+ if (OptionIter == OptionStrings.end()) {
+ // The input name did not match any known option string.
+ D.Diag(diag::err_drv_unknown_argument) << Val;
+ return;
+ }
+ // The option was specified without a float or double suffix.
+ // Make sure that the double entry was not already specified.
+ // The float entry will be checked below.
+ if (OptionStrings[ValBase.str() + 'd']) {
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
+ return;
+ }
+ }
+
+ if (OptionIter->second == true) {
+ // Duplicate option specified.
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
+ return;
+ }
+
+ // Mark the matched option as found. Do not allow duplicate specifiers.
+ OptionIter->second = true;
+
+ // If the precision was not specified, also mark the double entry as found.
+ if (ValBase.back() != 'f' && ValBase.back() != 'd')
+ OptionStrings[ValBase.str() + 'd'] = true;
+
+ // Build the output string.
+ StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
+ Out = Args.MakeArgString(Out + Prefix + Val);
+ if (i != NumOptions - 1)
+ Out = Args.MakeArgString(Out + ",");
+ }
+
+ OutStrings.push_back(Args.MakeArgString(Out));
+}
+
+static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features) {
+ // If -march=native, autodetect the feature list.
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ if (StringRef(A->getValue()) == "native") {
+ llvm::StringMap<bool> HostFeatures;
+ if (llvm::sys::getHostCPUFeatures(HostFeatures))
+ for (auto &F : HostFeatures)
+ Features.push_back(
+ Args.MakeArgString((F.second ? "+" : "-") + F.first()));
+ }
+ }
+
if (Triple.getArchName() == "x86_64h") {
// x86_64h implies quite a few of the more modern subtarget features
// for Haswell class CPUs, but not all of them. Opt-out of a few.
@@ -1566,29 +1710,29 @@ static void getX86TargetFeatures(const Driver & D,
Features.push_back("-fsgsbase");
}
- // Add features to comply with gcc on Android
+ const llvm::Triple::ArchType ArchType = Triple.getArch();
+ // Add features to be compatible with gcc for Android.
if (Triple.getEnvironment() == llvm::Triple::Android) {
- if (Triple.getArch() == llvm::Triple::x86_64) {
+ if (ArchType == llvm::Triple::x86_64) {
Features.push_back("+sse4.2");
Features.push_back("+popcnt");
} else
Features.push_back("+ssse3");
}
- // Set features according to the -arch flag on MSVC
+ // Set features according to the -arch flag on MSVC.
if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
StringRef Arch = A->getValue();
bool ArchUsed = false;
// First, look for flags that are shared in x86 and x86-64.
- if (Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::x86) {
+ if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
if (Arch == "AVX" || Arch == "AVX2") {
ArchUsed = true;
Features.push_back(Args.MakeArgString("+" + Arch.lower()));
}
}
// Then, look for x86-specific flags.
- if (Triple.getArch() == llvm::Triple::x86) {
+ if (ArchType == llvm::Triple::x86) {
if (Arch == "IA32") {
ArchUsed = true;
} else if (Arch == "SSE" || Arch == "SSE2") {
@@ -1602,11 +1746,9 @@ static void getX86TargetFeatures(const Driver & D,
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
- for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
- ie = Args.filtered_end();
- it != ie; ++it) {
- StringRef Name = (*it)->getOption().getName();
- (*it)->claim();
+ for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group)) {
+ StringRef Name = A->getOption().getName();
+ A->claim();
// Skip over "-m".
assert(Name.startswith("m") && "Invalid feature name.");
@@ -1622,9 +1764,7 @@ static void getX86TargetFeatures(const Driver & D,
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- if (!Args.hasFlag(options::OPT_mred_zone,
- options::OPT_mno_red_zone,
- true) ||
+ if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("-disable-red-zone");
@@ -1633,10 +1773,9 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
// that to be overridden with -mno-soft-float.
bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext));
- if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
- options::OPT_mno_soft_float,
- options::OPT_mimplicit_float,
- options::OPT_mno_implicit_float)) {
+ if (Arg *A = Args.getLastArg(
+ options::OPT_msoft_float, options::OPT_mno_soft_float,
+ options::OPT_mimplicit_float, options::OPT_mno_implicit_float)) {
const Option &O = A->getOption();
NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
O.matches(options::OPT_msoft_float));
@@ -1656,49 +1795,26 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
}
}
-static inline bool HasPICArg(const ArgList &Args) {
- return Args.hasArg(options::OPT_fPIC)
- || Args.hasArg(options::OPT_fpic);
-}
-
-static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) {
- return Args.getLastArg(options::OPT_G,
- options::OPT_G_EQ,
- options::OPT_msmall_data_threshold_EQ);
-}
-
-static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
- std::string value;
- if (HasPICArg(Args))
- value = "0";
- else if (Arg *A = GetLastSmallDataThresholdArg(Args)) {
- value = A->getValue();
- A->claim();
- }
- return value;
-}
-
void Clang::AddHexagonTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- CmdArgs.push_back("-fno-signed-char");
CmdArgs.push_back("-mqdsp6-compat");
CmdArgs.push_back("-Wreturn-type");
- std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
- if (!SmallDataThreshold.empty()) {
- CmdArgs.push_back ("-mllvm");
- CmdArgs.push_back(Args.MakeArgString(
- "-hexagon-small-data-threshold=" + SmallDataThreshold));
+ if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) {
+ std::string SmallDataThreshold = "-hexagon-small-data-threshold=";
+ SmallDataThreshold += v;
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold));
}
if (!Args.hasArg(options::OPT_fno_short_enums))
CmdArgs.push_back("-fshort-enums");
if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
- CmdArgs.push_back ("-mllvm");
- CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-hexagon-ieee-rnd-near");
}
- CmdArgs.push_back ("-mllvm");
- CmdArgs.push_back ("-machine-sink-split=0");
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-machine-sink-split=0");
}
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
@@ -1707,8 +1823,8 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
- for (unsigned I = 0, E = Split.size(); I != E; ++I) {
- const char *result = llvm::StringSwitch<const char *>(Split[I])
+ for (const StringRef Feature : Split) {
+ const char *result = llvm::StringSwitch<const char *>(Feature)
.Case("fp", "+fp-armv8")
.Case("simd", "+neon")
.Case("crc", "+crc")
@@ -1720,7 +1836,7 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
.Default(nullptr);
if (result)
Features.push_back(result);
- else if (Split[I] == "neon" || Split[I] == "noneon")
+ else if (Feature == "neon" || Feature == "noneon")
D.Diag(diag::err_drv_no_neon_modifier);
else
return false;
@@ -1734,7 +1850,8 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
std::vector<const char *> &Features) {
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
- if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
+ if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" ||
+ CPU == "cortex-a72") {
Features.push_back("+neon");
Features.push_back("+crc");
Features.push_back("+crypto");
@@ -1754,9 +1871,16 @@ static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
const ArgList &Args,
std::vector<const char *> &Features) {
- std::pair<StringRef, StringRef> Split = March.split("+");
- if (Split.first != "armv8-a")
+ std::string MarchLowerCase = March.lower();
+ std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
+
+ if (Split.first == "armv8-a" || Split.first == "armv8a") {
+ // ok, no additional features.
+ } else if (Split.first == "armv8.1-a" || Split.first == "armv8.1a") {
+ Features.push_back("+v8.1a");
+ } else {
return false;
+ }
if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
return false;
@@ -1769,7 +1893,8 @@ getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
std::vector<const char *> &Features) {
StringRef CPU;
- if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
+ std::string McpuLowerCase = Mcpu.lower();
+ if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
return false;
return true;
@@ -1795,7 +1920,8 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
std::vector<const char *> &Features) {
StringRef CPU;
std::vector<const char *> DecodedFeature;
- if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
+ std::string McpuLowerCase = Mcpu.lower();
+ if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
return false;
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
@@ -1835,8 +1961,7 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
}
// En/disable crc
- if (Arg *A = Args.getLastArg(options::OPT_mcrc,
- options::OPT_mnocrc)) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
if (A->getOption().matches(options::OPT_mcrc))
Features.push_back("+crc");
else
@@ -1870,9 +1995,8 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::ppc64le:
getPPCTargetFeatures(Args, Features);
break;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- getSparcTargetFeatures(Args, Features);
+ case llvm::Triple::systemz:
+ getSystemZTargetFeatures(Args, Features);
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
@@ -1918,32 +2042,22 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
if (!Triple.isMacOSX())
return false;
- return (!Triple.isMacOSXVersionLT(10,5) &&
+ return (!Triple.isMacOSXVersionLT(10, 5) &&
(Triple.getArch() == llvm::Triple::x86_64 ||
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;
-}
-
-/// addExceptionArgs - 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 disable C++ exceptions but enable
-/// Objective-C exceptions.
+/// 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
+/// disable C++ exceptions but enable Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
- const llvm::Triple &Triple,
- bool KernelOrKext,
+ const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+ const llvm::Triple &Triple = TC.getTriple();
+
if (KernelOrKext) {
// -mkernel and -fapple-kext imply no exceptions, so claim exception related
// arguments now to avoid warnings about unused arguments.
@@ -1956,31 +2070,50 @@ 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.
if (types::isObjC(InputType) &&
Args.hasFlag(options::OPT_fobjc_exceptions,
- options::OPT_fno_objc_exceptions,
- true)) {
+ options::OPT_fno_objc_exceptions, true)) {
CmdArgs.push_back("-fobjc-exceptions");
EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
}
if (types::isCXX(InputType)) {
- bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore;
- if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
- options::OPT_fno_cxx_exceptions,
- options::OPT_fexceptions,
- options::OPT_fno_exceptions))
+ // 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);
+ if (ExceptionArg)
CXXExceptionsEnabled =
- A->getOption().matches(options::OPT_fcxx_exceptions) ||
- A->getOption().matches(options::OPT_fexceptions);
+ ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) ||
+ ExceptionArg->getOption().matches(options::OPT_fexceptions);
if (CXXExceptionsEnabled) {
+ if (Triple.isPS4CPU()) {
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+ assert(ExceptionArg &&
+ "On the PS4 exceptions should only be enabled if passing "
+ "an argument");
+ if (RTTIMode == ToolChain::RM_DisabledExplicitly) {
+ const Arg *RTTIArg = TC.getRTTIArg();
+ assert(RTTIArg && "RTTI disabled explicitly but no RTTIArg!");
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << RTTIArg->getAsString(Args) << ExceptionArg->getAsString(Args);
+ } else if (RTTIMode == ToolChain::RM_EnabledImplicitly)
+ D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
+ } else
+ assert(TC.getRTTIMode() != ToolChain::RM_DisabledImplicitly);
+
CmdArgs.push_back("-fcxx-exceptions");
EH = true;
@@ -1991,8 +2124,7 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fexceptions");
}
-static bool ShouldDisableAutolink(const ArgList &Args,
- const ToolChain &TC) {
+static bool ShouldDisableAutolink(const ArgList &Args, const ToolChain &TC) {
bool Default = true;
if (TC.getTriple().isOSDarwin()) {
// The native darwin assembler doesn't support the linker_option directives,
@@ -2005,9 +2137,9 @@ static bool ShouldDisableAutolink(const ArgList &Args,
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
- bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
- options::OPT_fno_dwarf_directory_asm,
- TC.useIntegratedAs());
+ bool UseDwarfDirectory =
+ Args.hasFlag(options::OPT_fdwarf_directory_asm,
+ options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs());
return !UseDwarfDirectory;
}
@@ -2042,81 +2174,78 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
}
return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
- RelaxDefault);
+ RelaxDefault);
}
static void CollectArgsForIntegratedAssembler(Compilation &C,
const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D) {
- if (UseRelaxAll(C, Args))
- CmdArgs.push_back("-mrelax-all");
-
- // When passing -I arguments to the assembler we sometimes need to
- // unconditionally take the next argument. For example, when parsing
- // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
- // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
- // arg after parsing the '-I' arg.
- bool TakeNextArg = false;
-
- // When using an integrated assembler, translate -Wa, and -Xassembler
- // options.
- bool CompressDebugSections = false;
- for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
- options::OPT_Xassembler),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- A->claim();
+ if (UseRelaxAll(C, Args))
+ CmdArgs.push_back("-mrelax-all");
+
+ // When passing -I arguments to the assembler we sometimes need to
+ // unconditionally take the next argument. For example, when parsing
+ // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
+ // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
+ // arg after parsing the '-I' arg.
+ bool TakeNextArg = false;
+
+ // When using an integrated assembler, translate -Wa, and -Xassembler
+ // options.
+ bool CompressDebugSections = false;
+ for (const Arg *A :
+ Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+ A->claim();
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
- StringRef Value = A->getValue(i);
+ for (const StringRef Value : A->getValues()) {
if (TakeNextArg) {
CmdArgs.push_back(Value.data());
TakeNextArg = false;
continue;
}
- if (Value == "-force_cpusubtype_ALL") {
- // Do nothing, this is the default and we don't support anything else.
- } else if (Value == "-L") {
- CmdArgs.push_back("-msave-temp-labels");
- } else if (Value == "--fatal-warnings") {
- CmdArgs.push_back("-massembler-fatal-warnings");
- } else if (Value == "--noexecstack") {
- CmdArgs.push_back("-mnoexecstack");
- } else if (Value == "-compress-debug-sections" ||
- Value == "--compress-debug-sections") {
- CompressDebugSections = true;
- } else if (Value == "-nocompress-debug-sections" ||
- Value == "--nocompress-debug-sections") {
- CompressDebugSections = false;
- } else if (Value.startswith("-I")) {
- CmdArgs.push_back(Value.data());
- // We need to consume the next argument if the current arg is a plain
- // -I. The next arg will be the include directory.
- if (Value == "-I")
- TakeNextArg = true;
- } else if (Value.startswith("-gdwarf-")) {
- CmdArgs.push_back(Value.data());
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
+ if (Value == "-force_cpusubtype_ALL") {
+ // Do nothing, this is the default and we don't support anything else.
+ } else if (Value == "-L") {
+ CmdArgs.push_back("-msave-temp-labels");
+ } else if (Value == "--fatal-warnings") {
+ CmdArgs.push_back("-massembler-fatal-warnings");
+ } else if (Value == "--noexecstack") {
+ CmdArgs.push_back("-mnoexecstack");
+ } else if (Value == "-compress-debug-sections" ||
+ Value == "--compress-debug-sections") {
+ CompressDebugSections = true;
+ } else if (Value == "-nocompress-debug-sections" ||
+ Value == "--nocompress-debug-sections") {
+ CompressDebugSections = false;
+ } else if (Value.startswith("-I")) {
+ CmdArgs.push_back(Value.data());
+ // We need to consume the next argument if the current arg is a plain
+ // -I. The next arg will be the include directory.
+ if (Value == "-I")
+ TakeNextArg = true;
+ } else if (Value.startswith("-gdwarf-")) {
+ CmdArgs.push_back(Value.data());
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
- }
}
}
- if (CompressDebugSections) {
- if (llvm::zlib::isAvailable())
- CmdArgs.push_back("-compress-debug-sections");
- else
- D.Diag(diag::warn_debug_compression_unavailable);
- }
+ }
+ if (CompressDebugSections) {
+ if (llvm::zlib::isAvailable())
+ CmdArgs.push_back("-compress-debug-sections");
+ else
+ D.Diag(diag::warn_debug_compression_unavailable);
+ }
}
// Until ARM libraries are build separately, we have them all in one library
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
- // FIXME: handle 64-bit
if (TC.getTriple().isOSWindows() &&
- !TC.getTriple().isWindowsItaniumEnvironment())
+ !TC.getTriple().isWindowsItaniumEnvironment() &&
+ TC.getArch() == llvm::Triple::x86)
return "i386";
if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
return "arm";
@@ -2134,9 +2263,12 @@ static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
return Res;
}
-static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
- bool Shared = false,
- const char *Env = "") {
+SmallString<128> tools::getCompilerRT(const ToolChain &TC, StringRef Component,
+ bool Shared) {
+ const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
+ ? "-android"
+ : "";
+
bool IsOSWindows = TC.getTriple().isOSWindows();
StringRef Arch = getArchNameForCompilerRTLib(TC);
const char *Prefix = IsOSWindows ? "" : "lib";
@@ -2170,7 +2302,9 @@ 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) ||
Args.hasArg(options::OPT_coverage)))
return;
@@ -2178,19 +2312,63 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
}
+namespace {
+enum OpenMPRuntimeKind {
+ /// An unknown OpenMP runtime. We can't generate effective OpenMP code
+ /// without knowing what runtime to target.
+ OMPRT_Unknown,
+
+ /// The LLVM OpenMP runtime. When completed and integrated, this will become
+ /// the default for Clang.
+ OMPRT_OMP,
+
+ /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
+ /// this runtime but can swallow the pragmas, and find and link against the
+ /// runtime library itself.
+ OMPRT_GOMP,
+
+ /// The legacy name for the LLVM OpenMP runtime from when it was the Intel
+ /// OpenMP runtime. We support this mode for users with existing dependencies
+ /// on this runtime library name.
+ OMPRT_IOMP5
+};
+}
+
+/// Compute the desired OpenMP runtime from the flag provided.
+static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC,
+ const ArgList &Args) {
+ StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
+
+ const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
+ if (A)
+ RuntimeName = A->getValue();
+
+ auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
+ .Case("libomp", OMPRT_OMP)
+ .Case("libgomp", OMPRT_GOMP)
+ .Case("libiomp5", OMPRT_IOMP5)
+ .Default(OMPRT_Unknown);
+
+ if (RT == OMPRT_Unknown) {
+ if (A)
+ TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ else
+ // FIXME: We could use a nicer diagnostic here.
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
+ }
+
+ return RT;
+}
+
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared) {
- const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
- ? "-android"
- : "";
-
// Static runtimes must be forced into executable, so we wrap them in
// whole-archive.
if (!IsShared)
CmdArgs.push_back("-whole-archive");
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared,
- Env)));
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared)));
if (!IsShared)
CmdArgs.push_back("-no-whole-archive");
}
@@ -2251,20 +2429,23 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("dfsan");
if (SanArgs.needsLsanRt())
StaticRuntimes.push_back("lsan");
- if (SanArgs.needsMsanRt())
+ if (SanArgs.needsMsanRt()) {
StaticRuntimes.push_back("msan");
- if (SanArgs.needsTsanRt())
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("msan_cxx");
+ }
+ if (SanArgs.needsTsanRt()) {
StaticRuntimes.push_back("tsan");
- // WARNING: UBSan should always go last.
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("tsan_cxx");
+ }
if (SanArgs.needsUbsanRt()) {
- // If UBSan is not combined with another sanitizer, we need to pull in
- // sanitizer_common explicitly.
- if (StaticRuntimes.empty())
- HelperStaticRuntimes.push_back("san");
- StaticRuntimes.push_back("ubsan");
+ StaticRuntimes.push_back("ubsan_standalone");
if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("ubsan_cxx");
+ StaticRuntimes.push_back("ubsan_standalone_cxx");
}
+ if (SanArgs.needsSafeStackRt())
+ StaticRuntimes.push_back("safestack");
}
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
@@ -2291,27 +2472,49 @@ static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
return !StaticRuntimes.empty();
}
+static bool areOptimizationsEnabled(const ArgList &Args) {
+ // Find the last -O arg and see if it is non-zero.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ return !A->getOption().matches(options::OPT_O0);
+ // Defaults to -O0.
+ return false;
+}
+
static bool shouldUseFramePointerForTarget(const ArgList &Args,
const llvm::Triple &Triple) {
- switch (Triple.getArch()) {
- // Don't use a frame pointer on linux if optimizing for certain targets.
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::systemz:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- if (Triple.isOSLinux())
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- return true;
- case llvm::Triple::xcore:
+ // XCore never wants frame pointers, regardless of OS.
+ if (Triple.getArch() == llvm::Triple::xcore) {
return false;
- default:
- return true;
}
+
+ if (Triple.isOSLinux()) {
+ switch (Triple.getArch()) {
+ // Don't use a frame pointer on linux if optimizing for certain targets.
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return !areOptimizationsEnabled(Args);
+ default:
+ return true;
+ }
+ }
+
+ if (Triple.isOSWindows()) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ return !areOptimizationsEnabled(Args);
+ default:
+ // All other supported Windows ISAs use xdata unwind information, so frame
+ // pointers are not generally useful.
+ return false;
+ }
+ }
+
+ return true;
}
static bool shouldUseFramePointer(const ArgList &Args,
@@ -2329,6 +2532,9 @@ static bool shouldUseLeafFramePointer(const ArgList &Args,
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+ if (Triple.isPS4CPU())
+ return false;
+
return shouldUseFramePointerForTarget(Args, Triple);
}
@@ -2341,8 +2547,7 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
}
}
-static const char *SplitDebugName(const ArgList &Args,
- const InputInfoList &Inputs) {
+static const char *SplitDebugName(const ArgList &Args, const InputInfo &Input) {
Arg *FinalOutput = Args.getLastArg(options::OPT_o);
if (FinalOutput && Args.hasArg(options::OPT_c)) {
SmallString<128> T(FinalOutput->getValue());
@@ -2352,17 +2557,16 @@ static const char *SplitDebugName(const ArgList &Args,
// Use the compilation dir.
SmallString<128> T(
Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
- SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
+ SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
llvm::sys::path::replace_extension(F, "dwo");
T += F;
return Args.MakeArgString(F);
}
}
-static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
- const Tool &T, const JobAction &JA,
- const ArgList &Args, const InputInfo &Output,
- const char *OutFile) {
+static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
+ const JobAction &JA, const ArgList &Args,
+ const InputInfo &Output, const char *OutFile) {
ArgStringList ExtractArgs;
ExtractArgs.push_back("--extract-dwo");
@@ -2374,8 +2578,7 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
ExtractArgs.push_back(Output.getFilename());
ExtractArgs.push_back(OutFile);
- const char *Exec =
- Args.MakeArgString(TC.GetProgramPath("objcopy"));
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
// First extract the dwo sections.
C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs));
@@ -2431,24 +2634,17 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
CmdArgs.push_back(types::getTypeName(Input.getType()));
}
-static std::string getMSCompatibilityVersion(const char *VersionStr) {
- unsigned Version;
- if (StringRef(VersionStr).getAsInteger(10, Version))
- return "0";
-
+static VersionTuple getMSCompatibilityVersion(unsigned Version) {
if (Version < 100)
- return llvm::utostr_32(Version) + ".0";
+ return VersionTuple(Version);
if (Version < 10000)
- return llvm::utostr_32(Version / 100) + "." +
- llvm::utostr_32(Version % 100);
+ return VersionTuple(Version / 100, Version % 100);
unsigned Build = 0, Factor = 1;
- for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
+ for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
Build = Build + (Version % 10) * Factor;
- return llvm::utostr_32(Version / 100) + "." +
- llvm::utostr_32(Version % 100) + "." +
- llvm::utostr_32(Build);
+ return VersionTuple(Version / 100, Version % 100, Build);
}
// Claim options we don't want to warn if they are unused. We do this for
@@ -2461,13 +2657,173 @@ static void claimNoWarnArgs(const ArgList &Args) {
Args.ClaimAllArgs(options::OPT_fno_lto);
}
+static void appendUserToPath(SmallVectorImpl<char> &Result) {
+#ifdef LLVM_ON_UNIX
+ const char *Username = getenv("LOGNAME");
+#else
+ const char *Username = getenv("USERNAME");
+#endif
+ if (Username) {
+ // Validate that LoginName can be used in a path, and get its length.
+ size_t Len = 0;
+ for (const char *P = Username; *P; ++P, ++Len) {
+ if (!isAlphanumeric(*P) && *P != '_') {
+ Username = nullptr;
+ break;
+ }
+ }
+
+ if (Username && Len > 0) {
+ Result.append(Username, Username + Len);
+ return;
+ }
+ }
+
+// Fallback to user id.
+#ifdef LLVM_ON_UNIX
+ std::string UID = llvm::utostr(getuid());
+#else
+ // FIXME: Windows seems to have an 'SID' that might work.
+ std::string UID = "9999";
+#endif
+ Result.append(UID.begin(), UID.end());
+}
+
+VersionTuple visualstudio::getMSVCVersion(const Driver *D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ bool IsWindowsMSVC) {
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ IsWindowsMSVC) ||
+ Args.hasArg(options::OPT_fmsc_version) ||
+ Args.hasArg(options::OPT_fms_compatibility_version)) {
+ const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
+ const Arg *MSCompatibilityVersion =
+ Args.getLastArg(options::OPT_fms_compatibility_version);
+
+ if (MSCVersion && MSCompatibilityVersion) {
+ if (D)
+ D->Diag(diag::err_drv_argument_not_allowed_with)
+ << MSCVersion->getAsString(Args)
+ << MSCompatibilityVersion->getAsString(Args);
+ return VersionTuple();
+ }
+
+ if (MSCompatibilityVersion) {
+ VersionTuple MSVT;
+ if (MSVT.tryParse(MSCompatibilityVersion->getValue()) && D)
+ D->Diag(diag::err_drv_invalid_value)
+ << MSCompatibilityVersion->getAsString(Args)
+ << MSCompatibilityVersion->getValue();
+ return MSVT;
+ }
+
+ if (MSCVersion) {
+ unsigned Version = 0;
+ if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version) && D)
+ D->Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args)
+ << MSCVersion->getValue();
+ return getMSCompatibilityVersion(Version);
+ }
+
+ unsigned Major, Minor, Micro;
+ Triple.getEnvironmentVersion(Major, Minor, Micro);
+ if (Major || Minor || Micro)
+ return VersionTuple(Major, Minor, Micro);
+
+ return VersionTuple(18);
+ }
+ 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 {
- bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
- options::OPT_fapple_kext);
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, const char *LinkingOutput) const {
+ bool KernelOrKext =
+ Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -2476,7 +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.
//
@@ -2506,7 +2869,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
-
+
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
@@ -2527,7 +2890,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
// Also ignore explicit -force_cpusubtype_ALL option.
- (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
+ (void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
} else if (isa<PrecompileJobAction>(JA)) {
// Use PCH if the user requested it.
bool UsePCH = D.CCCUsePCH;
@@ -2544,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 ||
@@ -2565,9 +2932,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_Fragile;
} else {
- assert(JA.getType() == types::TY_PP_Asm &&
- "Unexpected output type!");
+ assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
}
+
+ // Preserve use-list order by default when emitting bitcode, so that
+ // loading the bitcode up in 'opt' or 'llc' and running passes gives the
+ // same result as running passes here. For LTO, we don't need to preserve
+ // the use-list order, since serialization to bitcode is part of the flow.
+ if (JA.getType() == types::TY_LLVM_BC)
+ CmdArgs.push_back("-emit-llvm-uselists");
}
// We normally speed up the clang process a bit by skipping destructors at
@@ -2576,7 +2949,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!C.isForDiagnostics())
CmdArgs.push_back("-disable-free");
- // Disable the verification pass in -asserts builds.
+// Disable the verification pass in -asserts builds.
#ifdef NDEBUG
CmdArgs.push_back("-disable-llvm-verifier");
#endif
@@ -2584,7 +2957,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Set the main file name, so that debug info works even with
// -save-temps.
CmdArgs.push_back("-main-file-name");
- CmdArgs.push_back(getBaseInputName(Args, Inputs));
+ CmdArgs.push_back(getBaseInputName(Args, Input));
// Some flags which affect the language (via preprocessor
// defines).
@@ -2609,10 +2982,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
CmdArgs.push_back("-analyzer-checker=osx");
-
+
CmdArgs.push_back("-analyzer-checker=deadcode");
-
- if (types::isCXX(Inputs[0].getType()))
+
+ if (types::isCXX(Input.getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
// Enable the following experimental checkers for testing.
@@ -2620,7 +2993,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
"-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
}
@@ -2650,7 +3023,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Android-specific defaults for PIC/PIE
if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
- switch (getToolChain().getTriple().getArch()) {
+ switch (getToolChain().getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
@@ -2676,16 +3049,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// OpenBSD-specific defaults for PIE
if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
- switch (getToolChain().getTriple().getArch()) {
+ switch (getToolChain().getArch()) {
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
IsPICLevelTwo = false; // "-fpie"
break;
case llvm::Triple::ppc:
+ case llvm::Triple::sparc:
case llvm::Triple::sparcv9:
IsPICLevelTwo = true; // "-fPIE"
break;
@@ -2703,10 +3077,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// used. If the last argument is any flavor of the '-fno-...' arguments,
// both PIC and PIE are disabled. Any PIE option implicitly enables PIC
// at the same level.
- Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
- options::OPT_fpic, options::OPT_fno_pic,
- options::OPT_fPIE, options::OPT_fno_PIE,
- options::OPT_fpie, options::OPT_fno_pie);
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
// is forced, then neither PIC nor PIE flags will have no effect.
if (!getToolChain().isPICDefaultForced()) {
@@ -2715,10 +3089,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
- PIC = PIE || O.matches(options::OPT_fPIC) ||
- O.matches(options::OPT_fpic);
- IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
- O.matches(options::OPT_fPIC);
+ PIC =
+ PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
+ IsPICLevelTwo =
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
} else {
PIE = PIC = false;
}
@@ -2745,7 +3119,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// uses it, and it isn't even valid on any OS but Darwin.
if (!getToolChain().getTriple().isOSDarwin())
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << getToolChain().getTriple().str();
+ << A->getSpelling() << getToolChain().getTriple().str();
// FIXME: Warn when this flag trumps some other PIC or PIE flag.
@@ -2781,6 +3155,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));
+ Args.AddLastArg(CmdArgs, options::OPT_fveclib);
+
if (!Args.hasFlag(options::OPT_fmerge_all_constants,
options::OPT_fno_merge_all_constants))
CmdArgs.push_back("-fno-merge-all-constants");
@@ -2789,14 +3165,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_frewrite_map_file) ||
Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
- for (arg_iterator
- MFI = Args.filtered_begin(options::OPT_frewrite_map_file,
- options::OPT_frewrite_map_file_EQ),
- MFE = Args.filtered_end();
- MFI != MFE; ++MFI) {
+ for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file,
+ options::OPT_frewrite_map_file_EQ)) {
CmdArgs.push_back("-frewrite-map-file");
- CmdArgs.push_back((*MFI)->getValue());
- (*MFI)->claim();
+ CmdArgs.push_back(A->getValue());
+ A->claim();
}
}
@@ -2816,7 +3189,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_freg_struct_return)) {
if (getToolChain().getArch() != llvm::Triple::x86) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << getToolChain().getTriple().str();
+ << A->getSpelling() << getToolChain().getTriple().str();
} else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
CmdArgs.push_back("-fpcc-struct-return");
} else {
@@ -2837,8 +3210,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool OFastEnabled = isOptimizationLevelFast(Args);
// If -Ofast is the optimization level, then -fstrict-aliasing should be
// enabled. This alias option is being used to simplify the hasFlag logic.
- OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
- options::OPT_fstrict_aliasing;
+ OptSpecifier StrictAliasingAliasOption =
+ OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing;
// We turn strict aliasing off by default if we're in CL mode, since MSVC
// doesn't do any TBAA.
bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
@@ -2861,30 +3234,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// If -Ofast is the optimization level, then -ffast-math should be enabled.
// This alias option is being used to simplify the getLastArg logic.
- OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
- options::OPT_ffast_math;
-
+ OptSpecifier FastMathAliasOption =
+ OFastEnabled ? options::OPT_Ofast : options::OPT_ffast_math;
+
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. The pattern for all of these is to
// default off the codegen optimizations, and if any flag enables them and no
// flag disables them after the flag enabling them, enable the codegen
// optimization. This is complicated by several "umbrella" flags.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_ffinite_math_only,
- options::OPT_fno_finite_math_only,
- options::OPT_fhonor_infinities,
- options::OPT_fno_honor_infinities))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only, options::OPT_fhonor_infinities,
+ options::OPT_fno_honor_infinities))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_finite_math_only &&
A->getOption().getID() != options::OPT_fhonor_infinities)
CmdArgs.push_back("-menable-no-infs");
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_ffinite_math_only,
- options::OPT_fno_finite_math_only,
- options::OPT_fhonor_nans,
- options::OPT_fno_honor_nans))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only, options::OPT_fhonor_nans,
+ options::OPT_fno_honor_nans))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_finite_math_only &&
A->getOption().getID() != options::OPT_fhonor_nans)
@@ -2892,10 +3263,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
bool MathErrno = getToolChain().IsMathErrnoDefault();
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_fmath_errno,
- options::OPT_fno_math_errno)) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_fmath_errno,
+ options::OPT_fno_math_errno)) {
// Turning on -ffast_math (with either flag) removes the need for MathErrno.
// However, turning *off* -ffast_math merely restores the toolchain default
// (which may be false).
@@ -2914,45 +3285,41 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// entire set of LLVM optimizations, so collect them through all the flag
// madness.
bool AssociativeMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations,
- options::OPT_fassociative_math,
- options::OPT_fno_associative_math))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fassociative_math, options::OPT_fno_associative_math))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
A->getOption().getID() != options::OPT_fno_associative_math)
AssociativeMath = true;
bool ReciprocalMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations,
- options::OPT_freciprocal_math,
- options::OPT_fno_reciprocal_math))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_freciprocal_math, options::OPT_fno_reciprocal_math))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
A->getOption().getID() != options::OPT_fno_reciprocal_math)
ReciprocalMath = true;
bool SignedZeros = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations,
- options::OPT_fsigned_zeros,
- options::OPT_fno_signed_zeros))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fsigned_zeros, options::OPT_fno_signed_zeros))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
A->getOption().getID() != options::OPT_fsigned_zeros)
SignedZeros = false;
bool TrappingMath = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
- options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations,
- options::OPT_ftrapping_math,
- options::OPT_fno_trapping_math))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_ftrapping_math, options::OPT_fno_trapping_math))
if (A->getOption().getID() != options::OPT_fno_fast_math &&
A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
A->getOption().getID() != options::OPT_ftrapping_math)
@@ -2961,8 +3328,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!TrappingMath)
CmdArgs.push_back("-menable-unsafe-fp-math");
+ if (!SignedZeros)
+ CmdArgs.push_back("-fno-signed-zeros");
+
+ if (ReciprocalMath)
+ CmdArgs.push_back("-freciprocal-math");
- // Validate and pass through -fp-contract option.
+ // Validate and pass through -fp-contract option.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffp_contract)) {
@@ -2972,7 +3344,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getOption().getName() << Val;
}
} else if (A->getOption().matches(options::OPT_ffast_math) ||
(OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
@@ -2981,6 +3353,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);
+
// We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
// and if we find them, tell the frontend to provide the appropriate
// preprocessor macros. This is distinct from enabling any optimizations as
@@ -2988,8 +3362,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// and deserialization, etc.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math))
- if (!A->getOption().matches(options::OPT_fno_fast_math))
- CmdArgs.push_back("-ffast-math");
+ if (!A->getOption().matches(options::OPT_fno_fast_math))
+ CmdArgs.push_back("-ffast-math");
if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
options::OPT_fno_fast_math))
if (A->getOption().matches(options::OPT_ffinite_math_only))
@@ -3052,7 +3426,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// FIXME: Handle -mtune=.
- (void) Args.hasArg(options::OPT_mtune_EQ);
+ (void)Args.hasArg(options::OPT_mtune_EQ);
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
CmdArgs.push_back("-mcode-model");
@@ -3060,9 +3434,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target cpu
- std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- llvm::Triple ETriple(ETripleStr);
- std::string CPU = getCPUName(Args, ETriple);
+ std::string CPU = getCPUName(Args, Triple);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPU));
@@ -3074,10 +3446,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target features
- getTargetFeatures(D, ETriple, Args, CmdArgs, false);
+ getTargetFeatures(D, Triple, Args, CmdArgs, false);
// Add target specific flags.
- switch(getToolChain().getArch()) {
+ switch (getToolChain().getArch()) {
default:
break;
@@ -3107,6 +3479,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -3136,16 +3509,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Explicitly error on some things we know we don't support and can't just
// ignore.
- types::ID InputType = Inputs[0].getType();
+ types::ID InputType = Input.getType();
if (!Args.hasArg(options::OPT_fallow_unsupported)) {
Arg *Unsupported;
- if (types::isCXX(InputType) &&
- getToolChain().getTriple().isOSDarwin() &&
+ if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() &&
getToolChain().getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
- << Unsupported->getOption().getName();
+ << Unsupported->getOption().getName();
}
}
@@ -3153,16 +3525,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_H);
if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
CmdArgs.push_back("-header-include-file");
- CmdArgs.push_back(D.CCPrintHeadersFilename ?
- D.CCPrintHeadersFilename : "-");
+ CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename
+ : "-");
}
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
CmdArgs.push_back("-diagnostic-log-file");
- CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
- D.CCLogDiagnosticsFilename : "-");
+ CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename
+ : "-");
}
// Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
@@ -3235,67 +3607,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-generate-type-units");
}
+ // CloudABI uses -ffunction-sections and -fdata-sections by default.
+ bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI;
+
if (Args.hasFlag(options::OPT_ffunction_sections,
- options::OPT_fno_function_sections, false)) {
+ options::OPT_fno_function_sections, UseSeparateSections)) {
CmdArgs.push_back("-ffunction-sections");
}
- if (Args.hasFlag(options::OPT_fdata_sections,
- options::OPT_fno_data_sections, false)) {
+ if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
+ UseSeparateSections)) {
CmdArgs.push_back("-fdata-sections");
}
- Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
-
- if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
- (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";
-
- 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.hasFlag(options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names, true))
+ CmdArgs.push_back("-fno-unique-section-names");
- if (Args.hasArg(options::OPT_fcoverage_mapping) &&
- !Args.hasArg(options::OPT_fprofile_instr_generate))
- 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");
+ Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
- 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.str())) {
- SmallString<128> Pwd;
- if (!llvm::sys::fs::current_path(Pwd)) {
- llvm::sys::path::append(Pwd, CoverageFilename.str());
- 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)) {
@@ -3303,7 +3634,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-nobuiltininc");
} else {
if (Args.hasArg(options::OPT_nostdlibinc))
- CmdArgs.push_back("-nostdsysteminc");
+ CmdArgs.push_back("-nostdsysteminc");
Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
}
@@ -3347,8 +3678,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
if (ARCMTEnabled) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-ccc-arcmt-migrate";
+ D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
+ << "-ccc-arcmt-migrate";
}
CmdArgs.push_back("-mt-migrate-directory");
CmdArgs.push_back(A->getValue());
@@ -3372,6 +3703,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
@@ -3407,10 +3739,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Warn about ignored options to clang.
- for (arg_iterator it = Args.filtered_begin(
- options::OPT_clang_ignored_gcc_optimization_f_Group),
- ie = Args.filtered_end(); it != ie; ++it) {
- D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
+ for (const Arg *A :
+ Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
+ D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
}
claimNoWarnArgs(Args);
@@ -3427,6 +3758,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
//
// If a std is supplied, only add -trigraphs if it follows the
// option.
+ bool ImplyVCPPCXXVer = false;
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
if (Std->getOption().matches(options::OPT_ansi))
if (types::isCXX(InputType))
@@ -3450,10 +3782,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// eventually we want to do all the standard defaulting here instead of
// splitting it between the driver and clang -cc1.
if (!types::isCXX(InputType))
- Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
- "-std=", /*Joined=*/true);
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=",
+ /*Joined=*/true);
else if (IsWindowsMSVC)
- CmdArgs.push_back("-std=c++11");
+ ImplyVCPPCXXVer = true;
Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
options::OPT_fno_trigraphs);
@@ -3540,7 +3872,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
}
-
if (Args.hasArg(options::OPT_relocatable_pch))
CmdArgs.push_back("-relocatable-pch");
@@ -3622,22 +3953,51 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
// AltiVec language extensions aren't relevant for assembling.
- if (!isa<PreprocessJobAction>(JA) ||
- Output.getType() != types::TY_PP_Asm)
+ if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
Args.AddLastArg(CmdArgs, options::OPT_faltivec);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
+ // Forward flags for OpenMP
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false))
+ switch (getOpenMPRuntime(getToolChain(), Args)) {
+ case OMPRT_OMP:
+ 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
+ // for a specific runtime library, we just don't pass the '-fopenmp' flag
+ // down to the actual compilation.
+ // FIXME: It would be better to have a mode which *only* omits IR
+ // generation based on the OpenMP support so that we get consistent
+ // semantic analysis, etc.
+ break;
+ }
+
const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
- Sanitize.addArgs(Args, CmdArgs);
+ Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType);
// Report an error for -faltivec on anything other than PowerPC.
- if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
- if (!(getToolChain().getArch() == llvm::Triple::ppc ||
- getToolChain().getArch() == llvm::Triple::ppc64 ||
- getToolChain().getArch() == llvm::Triple::ppc64le))
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "ppc/ppc64/ppc64le";
+ if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) {
+ const llvm::Triple::ArchType Arch = getToolChain().getArch();
+ if (!(Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 ||
+ Arch == llvm::Triple::ppc64le))
+ D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
+ << "ppc/ppc64/ppc64le";
+ }
if (getToolChain().SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
@@ -3665,8 +4025,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fno-strict-overflow implies -fwrapv if it isn't disabled, but
// -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
- if (Arg *A = Args.getLastArg(options::OPT_fwrapv,
- options::OPT_fno_wrapv)) {
+ if (Arg *A = Args.getLastArg(options::OPT_fwrapv, options::OPT_fno_wrapv)) {
if (A->getOption().matches(options::OPT_fwrapv))
CmdArgs.push_back("-fwrapv");
} else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
@@ -3686,23 +4045,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
-
// -stack-protector=0 is default.
unsigned StackProtectorLevel = 0;
- if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
- options::OPT_fstack_protector_all,
- options::OPT_fstack_protector_strong,
- options::OPT_fstack_protector)) {
+ if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
+ Args.ClaimAllArgs(options::OPT_fno_stack_protector);
+ Args.ClaimAllArgs(options::OPT_fstack_protector_all);
+ Args.ClaimAllArgs(options::OPT_fstack_protector_strong);
+ Args.ClaimAllArgs(options::OPT_fstack_protector);
+ } else if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+ options::OPT_fstack_protector_all,
+ options::OPT_fstack_protector_strong,
+ options::OPT_fstack_protector)) {
if (A->getOption().matches(options::OPT_fstack_protector)) {
- StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
- getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
+ StackProtectorLevel = std::max<unsigned>(
+ LangOptions::SSPOn,
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
} else if (A->getOption().matches(options::OPT_fstack_protector_strong))
StackProtectorLevel = LangOptions::SSPStrong;
else if (A->getOption().matches(options::OPT_fstack_protector_all))
StackProtectorLevel = LangOptions::SSPReq;
} else {
StackProtectorLevel =
- getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
}
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector");
@@ -3710,16 +4074,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// --param ssp-buffer-size=
- for (arg_iterator it = Args.filtered_begin(options::OPT__param),
- ie = Args.filtered_end(); it != ie; ++it) {
- StringRef Str((*it)->getValue());
+ for (const Arg *A : Args.filtered(options::OPT__param)) {
+ StringRef Str(A->getValue());
if (Str.startswith("ssp-buffer-size=")) {
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector-buffer-size");
// FIXME: Verify the argument is a valid integer.
CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
}
- (*it)->claim();
+ A->claim();
}
}
@@ -3730,7 +4093,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-force-align-stack");
}
if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
- false)) {
+ false)) {
CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
}
@@ -3739,8 +4102,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
}
- if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
- getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be)
+ if (Args.hasArg(options::OPT_mstack_probe_size)) {
+ StringRef Size = Args.getLastArgValue(options::OPT_mstack_probe_size);
+
+ if (!Size.empty())
+ CmdArgs.push_back(Args.MakeArgString("-mstack-probe-size=" + Size));
+ else
+ CmdArgs.push_back("-mstack-probe-size=0");
+ }
+
+ if (getToolChain().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getArch() == llvm::Triple::aarch64_be)
CmdArgs.push_back("-fallow-half-arguments-and-returns");
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
@@ -3759,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)) {
@@ -3798,53 +4159,56 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
getToolChain().IsBlocksDefault()) ||
- (Args.hasArg(options::OPT_fgnu_runtime) &&
- Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
- !Args.hasArg(options::OPT_fno_blocks))) {
+ (Args.hasArg(options::OPT_fgnu_runtime) &&
+ Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
+ !Args.hasArg(options::OPT_fno_blocks))) {
CmdArgs.push_back("-fblocks");
- if (!Args.hasArg(options::OPT_fgnu_runtime) &&
+ if (!Args.hasArg(options::OPT_fgnu_runtime) &&
!getToolChain().hasBlocksRuntime())
CmdArgs.push_back("-fblocks-runtime-optional");
}
- // -fmodules enables modules (off by default).
+ // -fmodules enables the use of precompiled modules (off by default).
// Users can pass -fno-cxx-modules to turn off modules support for
- // C++/Objective-C++ programs, which is a little less mature.
+ // C++/Objective-C++ programs.
bool HaveModules = false;
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
- bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
- options::OPT_fno_cxx_modules,
- true);
+ bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
+ options::OPT_fno_cxx_modules, true);
if (AllowedInCXX || !types::isCXX(InputType)) {
CmdArgs.push_back("-fmodules");
HaveModules = true;
}
}
- // -fmodule-maps enables module map processing (off by default) for header
- // checking. It is implied by -fmodules.
- if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
- false)) {
- CmdArgs.push_back("-fmodule-maps");
+ // -fmodule-maps enables implicit reading of module map files. By default,
+ // this is enabled if we are using precompiled modules.
+ if (Args.hasFlag(options::OPT_fimplicit_module_maps,
+ options::OPT_fno_implicit_module_maps, HaveModules)) {
+ CmdArgs.push_back("-fimplicit-module-maps");
}
// -fmodules-decluse checks that modules used are declared so (off by
// default).
if (Args.hasFlag(options::OPT_fmodules_decluse,
- options::OPT_fno_modules_decluse,
- false)) {
+ options::OPT_fno_modules_decluse, false)) {
CmdArgs.push_back("-fmodules-decluse");
}
// -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
// all #included headers are part of modules.
if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
- options::OPT_fno_modules_strict_decluse,
- false)) {
+ options::OPT_fno_modules_strict_decluse, false)) {
CmdArgs.push_back("-fmodules-strict-decluse");
}
+ // -fno-implicit-modules turns off implicitly compiling modules on demand.
+ if (!Args.hasFlag(options::OPT_fimplicit_modules,
+ options::OPT_fno_implicit_modules)) {
+ CmdArgs.push_back("-fno-implicit-modules");
+ }
+
// -fmodule-name specifies the module that is currently being built (or
// used for header checking by -fmodule-maps).
Args.AddLastArg(CmdArgs, options::OPT_fmodule_name);
@@ -3858,26 +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");
- 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
@@ -3911,10 +4276,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
- char TimeStamp[48];
- snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64,
- (uint64_t)Status.getLastModificationTime().toEpochTime());
- CmdArgs.push_back(Args.MakeArgString(TimeStamp));
+ CmdArgs.push_back(Args.MakeArgString(
+ "-fbuild-session-timestamp=" +
+ Twine((uint64_t)Status.getLastModificationTime().toEpochTime())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
@@ -3930,55 +4294,44 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
- options::OPT_faccess_control,
- false))
+ options::OPT_faccess_control, false))
CmdArgs.push_back("-fno-access-control");
// -felide-constructors is the default.
if (Args.hasFlag(options::OPT_fno_elide_constructors,
- options::OPT_felide_constructors,
- false))
+ options::OPT_felide_constructors, false))
CmdArgs.push_back("-fno-elide-constructors");
- // -frtti is default.
- if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
- KernelOrKext) {
- CmdArgs.push_back("-fno-rtti");
+ ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
- // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
- if (Sanitize.sanitizesVptr()) {
- std::string NoRttiArg =
- Args.getLastArg(options::OPT_mkernel,
- options::OPT_fapple_kext,
- options::OPT_fno_rtti)->getAsString(Args);
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fsanitize=vptr" << NoRttiArg;
- }
- }
+ if (KernelOrKext || (types::isCXX(InputType) &&
+ (RTTIMode == ToolChain::RM_DisabledExplicitly ||
+ RTTIMode == ToolChain::RM_DisabledImplicitly)))
+ CmdArgs.push_back("-fno-rtti");
// -fshort-enums=0 is default for all architectures except Hexagon.
- if (Args.hasFlag(options::OPT_fshort_enums,
- options::OPT_fno_short_enums,
- getToolChain().getArch() ==
- llvm::Triple::hexagon))
+ if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums,
+ getToolChain().getArch() == llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
// -fsigned-char is default.
- if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
- isSignedCharDefault(getToolChain().getTriple())))
+ if (Arg *A = Args.getLastArg(
+ options::OPT_fsigned_char, options::OPT_fno_signed_char,
+ options::OPT_funsigned_char, options::OPT_fno_unsigned_char)) {
+ if (A->getOption().matches(options::OPT_funsigned_char) ||
+ A->getOption().matches(options::OPT_fno_signed_char)) {
+ CmdArgs.push_back("-fno-signed-char");
+ }
+ } else if (!isSignedCharDefault(getToolChain().getTriple())) {
CmdArgs.push_back("-fno-signed-char");
-
- // -fthreadsafe-static is default.
- if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
- options::OPT_fno_threadsafe_statics))
- CmdArgs.push_back("-fno-threadsafe-statics");
+ }
// -fuse-cxa-atexit is default.
if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
options::OPT_fno_use_cxa_atexit,
!IsWindowsCygnus && !IsWindowsGNU &&
- getToolChain().getArch() != llvm::Triple::hexagon &&
- getToolChain().getArch() != llvm::Triple::xcore) ||
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
@@ -3987,37 +4340,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
IsWindowsMSVC))
CmdArgs.push_back("-fms-extensions");
+ // -fno-use-line-directives is default.
+ if (Args.hasFlag(options::OPT_fuse_line_directives,
+ options::OPT_fno_use_line_directives, false))
+ CmdArgs.push_back("-fuse-line-directives");
+
// -fms-compatibility=0 is default.
- if (Args.hasFlag(options::OPT_fms_compatibility,
+ if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
- (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
- options::OPT_fno_ms_extensions,
- true))))
+ (IsWindowsMSVC &&
+ Args.hasFlag(options::OPT_fms_extensions,
+ options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
- // -fms-compatibility-version=17.00 is default.
- if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
- IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
- Args.hasArg(options::OPT_fms_compatibility_version)) {
- const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
- const Arg *MSCompatibilityVersion =
- Args.getLastArg(options::OPT_fms_compatibility_version);
-
- if (MSCVersion && MSCompatibilityVersion)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << MSCVersion->getAsString(Args)
- << MSCompatibilityVersion->getAsString(Args);
-
- std::string Ver;
- if (MSCompatibilityVersion)
- Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
- else if (MSCVersion)
- Ver = getMSCompatibilityVersion(MSCVersion->getValue());
+ // -fms-compatibility-version=18.00 is default.
+ VersionTuple MSVT = visualstudio::getMSVCVersion(
+ &D, getToolChain().getTriple(), Args, IsWindowsMSVC);
+ if (!MSVT.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
- if (Ver.empty())
- CmdArgs.push_back("-fms-compatibility-version=17.00");
+ bool IsMSVC2015Compatible = MSVT.getMajor() >= 19;
+ if (ImplyVCPPCXXVer) {
+ if (IsMSVC2015Compatible)
+ CmdArgs.push_back("-std=c++14");
else
- CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
+ CmdArgs.push_back("-std=c++11");
}
// -fno-borland-extensions is default.
@@ -4025,6 +4373,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_borland_extensions, false))
CmdArgs.push_back("-fborland-extensions");
+ // -fthreadsafe-static is default, except for MSVC compatibility versions less
+ // than 19.
+ if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
+ options::OPT_fno_threadsafe_statics,
+ !IsWindowsMSVC || IsMSVC2015Compatible))
+ CmdArgs.push_back("-fno-threadsafe-statics");
+
// -fno-delayed-template-parsing is default, except for Windows where MSVC STL
// needs it.
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
@@ -4037,8 +4392,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_gnu_keywords))
A->render(Args, CmdArgs);
- if (Args.hasFlag(options::OPT_fgnu89_inline,
- options::OPT_fno_gnu89_inline,
+ if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline,
false))
CmdArgs.push_back("-fgnu89-inline");
@@ -4058,7 +4412,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
objcRuntime.isLegacyDispatchDefaultForArch(
- getToolChain().getArch()))) {
+ getToolChain().getArch()))) {
if (getToolChain().UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
@@ -4069,18 +4423,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// When ObjectiveC legacy runtime is in effect on MacOSX,
// turn on the option to do Array/Dictionary subscripting
// by default.
- if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
+ if (getToolChain().getArch() == llvm::Triple::x86 &&
getToolChain().getTriple().isMacOSX() &&
!getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
objcRuntime.isNeXTFamily())
CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
-
+
// -fencode-extended-block-signature=1 is default.
if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
CmdArgs.push_back("-fencode-extended-block-signature");
}
-
+
// Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
// NOTE: This logic is duplicated in ToolChains.cpp.
bool ARC = isObjCAutoRefCount(Args);
@@ -4119,21 +4473,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
GCArg = Args.getLastArg(options::OPT_fobjc_gc);
if (GCArg) {
if (ARC) {
- D.Diag(diag::err_drv_objc_gc_arr)
- << GCArg->getAsString(Args);
+ D.Diag(diag::err_drv_objc_gc_arr) << GCArg->getAsString(Args);
} else if (getToolChain().SupportsObjCGC()) {
GCArg->render(Args, CmdArgs);
} else {
// FIXME: We should move this to a hard error.
- D.Diag(diag::warn_drv_objc_gc_unsupported)
- << GCArg->getAsString(Args);
+ D.Diag(diag::warn_drv_objc_gc_unsupported) << GCArg->getAsString(Args);
}
}
+ if (Args.hasFlag(options::OPT_fapplication_extension,
+ options::OPT_fno_application_extension, false))
+ CmdArgs.push_back("-fapplication-extension");
+
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
- objcRuntime, CmdArgs);
+ addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, objcRuntime,
+ CmdArgs);
if (getToolChain().UseSjLjExceptions())
CmdArgs.push_back("-fsjlj-exceptions");
@@ -4143,6 +4499,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_assume_sane_operator_new))
CmdArgs.push_back("-fno-assume-sane-operator-new");
+ // -fsized-deallocation is off by default, as it is an ABI-breaking change for
+ // most platforms.
+ if (Args.hasFlag(options::OPT_fsized_deallocation,
+ options::OPT_fno_sized_deallocation, false))
+ CmdArgs.push_back("-fsized-deallocation");
+
// -fconstant-cfstrings is default, and may be subject to argument translation
// on Darwin.
if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
@@ -4159,8 +4521,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fno-pascal-strings is default, only pass non-default.
if (Args.hasFlag(options::OPT_fpascal_strings,
- options::OPT_fno_pascal_strings,
- false))
+ options::OPT_fno_pascal_strings, false))
CmdArgs.push_back("-fpascal-strings");
// Honor -fpack-struct= and -fpack-struct, if given. Note that
@@ -4204,28 +4565,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fsigned_bitfields,
options::OPT_funsigned_bitfields))
D.Diag(diag::warn_drv_clang_unsupported)
- << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
+ << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
// -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
- if (!Args.hasFlag(options::OPT_ffor_scope,
- options::OPT_fno_for_scope))
+ if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope))
D.Diag(diag::err_drv_clang_unsupported)
- << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
+ << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
// -finput_charset=UTF-8 is default. Reject others
- if (Arg *inputCharset = Args.getLastArg(
- options::OPT_finput_charset_EQ)) {
- StringRef value = inputCharset->getValue();
- if (value != "UTF-8")
- D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value;
+ if (Arg *inputCharset = Args.getLastArg(options::OPT_finput_charset_EQ)) {
+ StringRef value = inputCharset->getValue();
+ if (value != "UTF-8")
+ D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args)
+ << value;
}
// -fexec_charset=UTF-8 is default. Reject others
- if (Arg *execCharset = Args.getLastArg(
- options::OPT_fexec_charset_EQ)) {
- StringRef value = execCharset->getValue();
- if (value != "UTF-8")
- D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args) << value;
+ if (Arg *execCharset = Args.getLastArg(options::OPT_fexec_charset_EQ)) {
+ StringRef value = execCharset->getValue();
+ if (value != "UTF-8")
+ D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args)
+ << value;
}
// -fcaret-diagnostics is default.
@@ -4244,22 +4604,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fdiagnostics-show-option");
if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
+ Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
CmdArgs.push_back("-fdiagnostics-show-category");
CmdArgs.push_back(A->getValue());
}
- if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
+ if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(
- options::OPT_fdiagnostics_show_note_include_stack,
- options::OPT_fno_diagnostics_show_note_include_stack)) {
+ options::OPT_fdiagnostics_show_note_include_stack,
+ options::OPT_fno_diagnostics_show_note_include_stack)) {
if (A->getOption().matches(
- options::OPT_fdiagnostics_show_note_include_stack))
+ options::OPT_fdiagnostics_show_note_include_stack))
CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
else
CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
@@ -4297,7 +4656,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ShowColors = Colors_Auto;
else
getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
- << ("-fdiagnostics-color=" + value).str();
+ << ("-fdiagnostics-color=" + value).str();
}
}
if (ShowColors == Colors_On ||
@@ -4311,8 +4670,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
- if (!Args.hasFlag(options::OPT_fshow_column,
- options::OPT_fno_show_column,
+ if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
true))
CmdArgs.push_back("-fno-show-column");
@@ -4320,26 +4678,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_spell_checking))
CmdArgs.push_back("-fno-spell-checking");
-
// -fno-asm-blocks is default.
if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
false))
CmdArgs.push_back("-fasm-blocks");
+ // -fgnu-inline-asm is default.
+ if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
+ options::OPT_fno_gnu_inline_asm, true))
+ CmdArgs.push_back("-fno-gnu-inline-asm");
+
// Enable vectorization per default according to the optimization level
// selected. For optimization levels that want vectorization we use the alias
// option to simplify the hasFlag logic.
bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
- OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
- options::OPT_fvectorize;
+ OptSpecifier VectorizeAliasOption =
+ EnableVec ? options::OPT_O_Group : options::OPT_fvectorize;
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
// -fslp-vectorize is enabled based on the optimization level selected.
bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
- OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
- options::OPT_fslp_vectorize;
+ OptSpecifier SLPVectAliasOption =
+ EnableSLPVec ? options::OPT_O_Group : options::OPT_fslp_vectorize;
if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
@@ -4374,16 +4736,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
- // le32-specific flags:
+ // le32-specific flags:
// -fno-math-builtin: clang should not convert math builtins to intrinsics
// by default.
if (getToolChain().getArch() == llvm::Triple::le32) {
CmdArgs.push_back("-fno-math-builtin");
}
- // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
- //
- // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
+// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
+//
+// FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
if (getToolChain().getTriple().isOSDarwin() &&
(getToolChain().getArch() == llvm::Triple::arm ||
@@ -4415,7 +4777,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_dM);
Args.AddLastArg(CmdArgs, options::OPT_dD);
-
+
// Handle serialized diagnostics.
if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
CmdArgs.push_back("-serialize-diagnostic-file");
@@ -4434,23 +4796,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// parser.
Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
bool OptDisabled = false;
- for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
- ie = Args.filtered_end(); it != ie; ++it) {
- (*it)->claim();
+ for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
+ A->claim();
// We translate this by hand to the -cc1 argument, since nightly test uses
// it and developers have been trained to spell it with -mllvm.
- if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") {
+ if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
CmdArgs.push_back("-disable-llvm-optzns");
OptDisabled = true;
} else
- (*it)->render(Args, CmdArgs);
+ A->render(Args, CmdArgs);
}
// With -save-temps, we want to save the unoptimized bitcode output from the
// CompileJobAction, so disable optimizations if they are not already
// disabled.
- if (Args.hasArg(options::OPT_save_temps) && !OptDisabled &&
+ if (C.getDriver().isSaveTempsEnabled() && !OptDisabled &&
isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-optzns");
@@ -4463,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);
@@ -4485,29 +4844,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
SmallString<256> Flags;
Flags += Exec;
- for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+ for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
- EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
+ EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
CmdArgs.push_back("-dwarf-debug-flags");
- CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+ CmdArgs.push_back(Args.MakeArgString(Flags));
}
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
- getToolChain().getTriple().isOSLinux() &&
- (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
- isa<BackendJobAction>(JA));
+ getToolChain().getTriple().isOSLinux() &&
+ (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
+ isa<BackendJobAction>(JA));
const char *SplitDwarfOut;
if (SplitDwarf) {
CmdArgs.push_back("-split-dwarf-file");
- SplitDwarfOut = SplitDebugName(Args, Inputs);
+ SplitDwarfOut = SplitDebugName(Args, Input);
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 &&
@@ -4520,7 +4889,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-
// Handle the debug info splitting at object creation time if we're
// creating an object.
// TODO: Currently only works on linux with newer objcopy.
@@ -4529,8 +4897,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_pg))
if (Args.hasArg(options::OPT_fomit_frame_pointer))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fomit-frame-pointer" << A->getAsString(Args);
+ D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
+ << A->getAsString(Args);
// Claim some arguments which clang supports automatically.
@@ -4555,9 +4923,9 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
ArgStringList &cmdArgs,
RewriteKind rewriteKind) const {
// Look for the controlling runtime option.
- Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
- options::OPT_fgnu_runtime,
- options::OPT_fobjc_runtime_EQ);
+ Arg *runtimeArg =
+ args.getLastArg(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
+ options::OPT_fobjc_runtime_EQ);
// Just forward -fobjc-runtime= to the frontend. This supercedes
// options about fragility.
@@ -4567,7 +4935,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
StringRef value = runtimeArg->getValue();
if (runtime.tryParse(value)) {
getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
- << value;
+ << value;
}
runtimeArg->render(args, cmdArgs);
@@ -4590,26 +4958,25 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
else if (value == "3")
objcABIVersion = 3;
else
- getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
- << value;
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << value;
} else {
// Otherwise, determine if we are using the non-fragile ABI.
- bool nonFragileABIIsDefault =
- (rewriteKind == RK_NonFragile ||
- (rewriteKind == RK_None &&
- getToolChain().IsObjCNonFragileABIDefault()));
+ bool nonFragileABIIsDefault =
+ (rewriteKind == RK_NonFragile ||
+ (rewriteKind == RK_None &&
+ getToolChain().IsObjCNonFragileABIDefault()));
if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
options::OPT_fno_objc_nonfragile_abi,
nonFragileABIIsDefault)) {
- // Determine the non-fragile ABI version to use.
+// Determine the non-fragile ABI version to use.
#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
unsigned nonFragileABIVersion = 1;
#else
unsigned nonFragileABIVersion = 2;
#endif
- if (Arg *abiArg = args.getLastArg(
- options::OPT_fobjc_nonfragile_abi_version_EQ)) {
+ if (Arg *abiArg =
+ args.getLastArg(options::OPT_fobjc_nonfragile_abi_version_EQ)) {
StringRef value = abiArg->getValue();
if (value == "1")
nonFragileABIVersion = 1;
@@ -4617,7 +4984,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
nonFragileABIVersion = 2;
else
getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
- << value;
+ << value;
}
objcABIVersion = 1 + nonFragileABIVersion;
@@ -4646,30 +5013,30 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
break;
}
- // -fnext-runtime
+ // -fnext-runtime
} else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
// On Darwin, make this use the default behavior for the toolchain.
if (getToolChain().getTriple().isOSDarwin()) {
runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
- // Otherwise, build for a generic macosx port.
+ // Otherwise, build for a generic macosx port.
} else {
runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
}
- // -fgnu-runtime
+ // -fgnu-runtime
} else {
assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
// Legacy behaviour is to target the gnustep runtime if we are i
// non-fragile mode or the GCC runtime in fragile mode.
if (isNonFragile)
- runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6));
+ runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1, 6));
else
runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
}
- cmdArgs.push_back(args.MakeArgString(
- "-fobjc-runtime=" + runtime.getAsString()));
+ cmdArgs.push_back(
+ args.MakeArgString("-fobjc-runtime=" + runtime.getAsString()));
return runtime;
}
@@ -4696,19 +5063,33 @@ 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);
+
+ std::vector<std::string> EHArgs =
+ Args.getAllArgValues(options::OPT__SLASH_EH);
for (auto EHVal : EHArgs) {
for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
switch (EHVal[I]) {
- case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
- case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
- case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
- default: break;
+ case 'a':
+ EH.Asynch = maybeConsumeDash(EHVal, I);
+ continue;
+ case 'c':
+ EH.NoExceptC = maybeConsumeDash(EHVal, I);
+ continue;
+ case 's':
+ EH.Synch = maybeConsumeDash(EHVal, I);
+ continue;
+ default:
+ break;
}
D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
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;
}
@@ -4723,33 +5104,33 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
RTOptionID = A->getOption().getID();
- switch(RTOptionID) {
- case options::OPT__SLASH_MD:
- if (Args.hasArg(options::OPT__SLASH_LDd))
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-D_DLL");
- CmdArgs.push_back("--dependent-lib=msvcrt");
- break;
- case options::OPT__SLASH_MDd:
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MD:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-D_DLL");
- CmdArgs.push_back("--dependent-lib=msvcrtd");
- break;
- case options::OPT__SLASH_MT:
- if (Args.hasArg(options::OPT__SLASH_LDd))
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("--dependent-lib=libcmt");
- break;
- case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrt");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrtd");
+ break;
+ case options::OPT__SLASH_MT:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("--dependent-lib=libcmtd");
- break;
- default:
- llvm_unreachable("Unexpected option ID.");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmt");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmtd");
+ break;
+ default:
+ llvm_unreachable("Unexpected option ID.");
}
// This provides POSIX compatibility (maps 'open' to '_open'), which most
@@ -4772,8 +5153,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
EHFlags EH = parseClangCLEHFlags(D, Args);
// FIXME: Do something with NoExceptC.
if (EH.Synch || EH.Asynch) {
- CmdArgs.push_back("-fexceptions");
CmdArgs.push_back("-fcxx-exceptions");
+ CmdArgs.push_back("-fexceptions");
}
// /EP should expand to -E -P.
@@ -4782,6 +5163,19 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
CmdArgs.push_back("-P");
}
+ unsigned VolatileOptionID;
+ if (getToolChain().getArch() == llvm::Triple::x86_64 ||
+ getToolChain().getArch() == llvm::Triple::x86)
+ VolatileOptionID = options::OPT__SLASH_volatile_ms;
+ else
+ VolatileOptionID = options::OPT__SLASH_volatile_iso;
+
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group))
+ VolatileOptionID = A->getOption().getID();
+
+ if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
+ CmdArgs.push_back("-fms-volatile");
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -4820,15 +5214,25 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
}
}
-visualstudio::Compile *Clang::getCLFallback() const {
+visualstudio::Compiler *Clang::getCLFallback() const {
if (!CLFallback)
- CLFallback.reset(new visualstudio::Compile(getToolChain()));
+ CLFallback.reset(new visualstudio::Compiler(getToolChain()));
return CLFallback.get();
}
+void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ StringRef CPUName;
+ StringRef ABIName;
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName.data());
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
@@ -4850,8 +5254,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr =
- getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
+ std::string TripleStr =
+ getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Set the output mode, we currently only expect to be used as a real
@@ -4862,10 +5266,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Set the main file name, so that debug info works even with
// -save-temps or preprocessed assembly.
CmdArgs.push_back("-main-file-name");
- CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));
+ CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
// Add the target cpu
- const llvm::Triple &Triple = getToolChain().getTriple();
+ const llvm::Triple Triple(TripleStr);
std::string CPU = getCPUName(Args, Triple);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
@@ -4877,7 +5281,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
getTargetFeatures(D, Triple, Args, CmdArgs, true);
// Ignore explicit -force_cpusubtype_ALL option.
- (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
+ (void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
+
+ // Pass along any -I options so we get proper .include search paths.
+ Args.AddAllArgs(CmdArgs, options::OPT_I_Group);
// Determine the original source input.
const Action *SourceAction = &JA;
@@ -4921,27 +5328,38 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
SmallString<256> Flags;
const char *Exec = getToolChain().getDriver().getClangProgramPath();
Flags += Exec;
- for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+ for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
- EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
+ EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
CmdArgs.push_back("-dwarf-debug-flags");
- CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+ CmdArgs.push_back(Args.MakeArgString(Flags));
}
// FIXME: Add -static support, once we have it.
+ // Add target specific flags.
+ switch (getToolChain().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+ }
+
// Consume all the warning flags. Usually this would be handled more
// gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
// doesn't handle that so rather than warning about unused flags that are
// actually used, we'll lie by omission instead.
// FIXME: Stop lying and consume only the appropriate driver flags
- for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
- ie = Args.filtered_end();
- it != ie; ++it)
- (*it)->claim();
+ for (const Arg *A : Args.filtered(options::OPT_W_Group))
+ A->claim();
CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
getToolChain().getDriver());
@@ -4964,15 +5382,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs));
+ SplitDebugName(Args, Input));
}
void GnuTool::anchor() {}
void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
+ const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -5004,7 +5421,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getTriple().isOSDarwin()) {
CmdArgs.push_back("-arch");
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
+ Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
}
// Try to force gcc to match the tool chain we want, if we recognize
@@ -5012,7 +5429,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
//
// FIXME: The triple class should directly provide the information we want
// here.
- llvm::Triple::ArchType Arch = getToolChain().getArch();
+ const llvm::Triple::ArchType Arch = getToolChain().getArch();
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
CmdArgs.push_back("-m32");
else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
@@ -5027,8 +5444,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsyntax-only");
}
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
// Only pass -x if gcc will understand it; otherwise hope gcc
// understands the suffix correctly. The main use case this would go
@@ -5043,13 +5459,12 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
D.Diag(diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString();
+ << getToolChain().getTripleString();
else if (II.getType() == types::TY_AST)
- D.Diag(diag::err_drv_no_ast_support)
- << getToolChain().getTripleString();
+ D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString();
else if (II.getType() == types::TY_ModuleFile)
D.Diag(diag::err_drv_no_module_support)
- << getToolChain().getTripleString();
+ << getToolChain().getTripleString();
if (types::canTypeBeUserSpecified(II.getType())) {
CmdArgs.push_back("-x");
@@ -5081,48 +5496,51 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
} else
GCCName = "gcc";
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
+void gcc::Preprocessor::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
CmdArgs.push_back("-E");
}
-void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
+void gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
+ switch (JA.getType()) {
// If -flto, etc. are present then make sure not to force assembly output.
- if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
- JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
+ case types::TY_LLVM_IR:
+ case types::TY_LTO_IR:
+ case types::TY_LLVM_BC:
+ case types::TY_LTO_BC:
CmdArgs.push_back("-c");
- else {
- if (JA.getType() != types::TY_PP_Asm)
- D.Diag(diag::err_drv_invalid_gcc_output_type)
- << getTypeName(JA.getType());
-
+ break;
+ case types::TY_PP_Asm:
CmdArgs.push_back("-S");
+ break;
+ case types::TY_Nothing:
+ CmdArgs.push_back("-fsyntax-only");
+ break;
+ default:
+ D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());
}
}
-void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
+void gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
// The types are (hopefully) good enough.
}
// Hexagon tools start.
-void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
-
-}
-void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {}
+void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
const Driver &D = getToolChain().getDriver();
@@ -5142,13 +5560,10 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsyntax-only");
}
- std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
- if (!SmallDataThreshold.empty())
- CmdArgs.push_back(
- Args.MakeArgString(std::string("-G") + SmallDataThreshold));
+ if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args))
+ CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v));
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
// Only pass -x if gcc will understand it; otherwise hope gcc
// understands the suffix correctly. The main use case this would go
@@ -5163,18 +5578,19 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString();
+ << getToolChain().getTripleString();
else if (II.getType() == types::TY_AST)
D.Diag(clang::diag::err_drv_no_ast_support)
- << getToolChain().getTripleString();
+ << getToolChain().getTripleString();
else if (II.getType() == types::TY_ModuleFile)
D.Diag(diag::err_drv_no_module_support)
- << getToolChain().getTripleString();
+ << getToolChain().getTripleString();
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
- // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ?
+ // Don't render as input, we need gcc to do the translations.
+ // FIXME: Pranav: What is this ?
II.getInputArg().render(Args, CmdArgs);
}
@@ -5183,23 +5599,21 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
+void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
// The types are (hopefully) good enough.
}
-void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
+ const toolchains::Hexagon_TC &ToolChain,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *LinkingOutput) {
- const toolchains::Hexagon_TC& ToolChain =
- static_cast<const toolchains::Hexagon_TC&>(getToolChain());
const Driver &D = ToolChain.getDriver();
- ArgStringList CmdArgs;
-
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
@@ -5209,6 +5623,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
+ bool useG0 = false;
bool useShared = buildingLib && !hasStaticArg;
//----------------------------------------------------------------------------
@@ -5242,10 +5657,9 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (buildPIE && !buildingLib)
CmdArgs.push_back("-pie");
- std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
- if (!SmallDataThreshold.empty()) {
- CmdArgs.push_back(
- Args.MakeArgString(std::string("-G") + SmallDataThreshold));
+ if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) {
+ CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v));
+ useG0 = toolchains::Hexagon_TC::UsesG0(v);
}
//----------------------------------------------------------------------------
@@ -5259,21 +5673,18 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
const std::string RootDir =
toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/";
- const std::string StartFilesDir = RootDir
- + "hexagon/lib"
- + (buildingLib
- ? MarchG0Suffix : MarchSuffix);
+ const std::string StartFilesDir =
+ RootDir + "hexagon/lib" + (useG0 ? MarchG0Suffix : MarchSuffix);
//----------------------------------------------------------------------------
// moslib
//----------------------------------------------------------------------------
std::vector<std::string> oslibs;
- bool hasStandalone= false;
+ bool hasStandalone = false;
- for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ),
- ie = Args.filtered_end(); it != ie; ++it) {
- (*it)->claim();
- oslibs.push_back((*it)->getValue());
+ for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
+ A->claim();
+ oslibs.emplace_back(A->getValue());
hasStandalone = hasStandalone || (oslibs.back() == "standalone");
}
if (oslibs.empty()) {
@@ -5289,7 +5700,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!buildingLib) {
if (hasStandalone) {
CmdArgs.push_back(
- Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
+ Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
}
CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
}
@@ -5327,9 +5738,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--start-group");
if (!buildingLib) {
- for(std::vector<std::string>::iterator i = oslibs.begin(),
- e = oslibs.end(); i != e; ++i)
- CmdArgs.push_back(Args.MakeArgString("-l" + *i));
+ for (const std::string &Lib : oslibs)
+ CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
CmdArgs.push_back("-lc");
}
CmdArgs.push_back("-lgcc");
@@ -5344,6 +5754,20 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
}
+}
+
+void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ const toolchains::Hexagon_TC &ToolChain =
+ static_cast<const toolchains::Hexagon_TC &>(getToolChain());
+
+ ArgStringList CmdArgs;
+ constructHexagonLinkArgs(C, JA, ToolChain, Output, Inputs, Args, CmdArgs,
+ LinkingOutput);
std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
@@ -5351,10 +5775,9 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
// Hexagon tools end.
-/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
-const char *arm::getARMCPUForMArch(const ArgList &Args,
- const llvm::Triple &Triple) {
- StringRef MArch;
+const std::string arm::getARMArch(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ std::string MArch;
if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
// Otherwise, if we have -march= choose the base CPU for that arch.
MArch = A->getValue();
@@ -5362,27 +5785,50 @@ const char *arm::getARMCPUForMArch(const ArgList &Args,
// Otherwise, use the Arch from the triple.
MArch = Triple.getArchName();
}
+ MArch = StringRef(MArch).lower();
// Handle -march=native.
if (MArch == "native") {
std::string CPU = llvm::sys::getHostCPUName();
if (CPU != "generic") {
- // Translate the native cpu into the architecture. The switch below will
- // then chose the minimum cpu for that arch.
- MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
+ // Translate the native cpu into the architecture suffix for that CPU.
+ const char *Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch);
+ // If there is no valid architecture suffix for this CPU we don't know how
+ // to handle it, so return no architecture.
+ if (strcmp(Suffix, "") == 0)
+ MArch = "";
+ else
+ MArch = std::string("arm") + Suffix;
}
}
- return Triple.getARMCPUForArch(MArch);
+ return MArch;
+}
+/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
+const char *arm::getARMCPUForMArch(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ std::string MArch = getARMArch(Args, Triple);
+ // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
+ // here means an -march=native that we can't handle, so instead return no CPU.
+ if (MArch.empty())
+ return "";
+
+ // We need to return an empty string here on invalid MArch values as the
+ // various places that call this function can't cope with a null result.
+ const char *result = Triple.getARMCPUForArch(MArch);
+ if (result)
+ return result;
+ else
+ return "";
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
-StringRef arm::getARMTargetCPU(const ArgList &Args,
- const llvm::Triple &Triple) {
+std::string arm::getARMTargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
// FIXME: Warn on inconsistent use of -mcpu and -march.
// If we have -mcpu=, use that.
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- StringRef MCPU = A->getValue();
+ std::string MCPU = StringRef(A->getValue()).lower();
// Handle -mcpu=native.
if (MCPU == "native")
return llvm::sys::getHostCPUName();
@@ -5394,48 +5840,48 @@ StringRef arm::getARMTargetCPU(const ArgList &Args,
}
/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
-/// CPU.
-//
+/// CPU (or Arch, if CPU is generic).
// FIXME: This is redundant with -mcpu, why does LLVM use this.
-// FIXME: tblgen this, or kill it!
-const char *arm::getLLVMArchSuffixForARM(StringRef CPU) {
- return llvm::StringSwitch<const char *>(CPU)
- .Case("strongarm", "v4")
- .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
- .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
- .Cases("arm920", "arm920t", "arm922t", "v4t")
- .Cases("arm940t", "ep9312","v4t")
- .Cases("arm10tdmi", "arm1020t", "v5")
- .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e")
- .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e")
- .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e")
- .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6")
- .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
- .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
- .Cases("cortex-r4", "cortex-r5", "v7r")
- .Case("cortex-m0", "v6m")
- .Case("cortex-m3", "v7m")
- .Cases("cortex-m4", "cortex-m7", "v7em")
- .Case("swift", "v7s")
- .Case("cyclone", "v8")
- .Cases("cortex-a53", "cortex-a57", "v8")
- .Default("");
-}
-
-void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) {
+const char *arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch) {
+ if (CPU == "generic" &&
+ llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_ARMV8_1A)
+ return "v8.1a";
+
+ unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
+ if (ArchKind == llvm::ARM::AK_INVALID)
+ return "";
+ return llvm::ARMTargetParser::getSubArch(ArchKind);
+}
+
+void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
+ const llvm::Triple &Triple) {
if (Args.hasArg(options::OPT_r))
return;
- StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple));
- const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
- .Cases("v4", "v4t", "v5", "v5e", nullptr)
- .Cases("v6", "v6t2", nullptr)
- .Default("--be8");
-
- if (LinkFlag)
- CmdArgs.push_back(LinkFlag);
+ // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
+ // to generate BE-8 executables.
+ if (getARMSubArchVersionNumber(Triple) >= 7 || isARMMProfile(Triple))
+ CmdArgs.push_back("--be8");
+}
+
+mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
+ return (NanEncoding)llvm::StringSwitch<int>(CPU)
+ .Case("mips1", NanLegacy)
+ .Case("mips2", NanLegacy)
+ .Case("mips3", NanLegacy)
+ .Case("mips4", NanLegacy)
+ .Case("mips5", NanLegacy)
+ .Case("mips32", NanLegacy)
+ .Case("mips32r2", NanLegacy)
+ .Case("mips32r3", NanLegacy | Nan2008)
+ .Case("mips32r5", NanLegacy | Nan2008)
+ .Case("mips32r6", Nan2008)
+ .Case("mips64", NanLegacy)
+ .Case("mips64r2", NanLegacy)
+ .Case("mips64r3", NanLegacy | Nan2008)
+ .Case("mips64r5", NanLegacy | Nan2008)
+ .Case("mips64r6", Nan2008)
+ .Default(NanLegacy);
}
bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
@@ -5451,20 +5897,20 @@ bool mips::isUCLibc(const ArgList &Args) {
bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
return llvm::StringSwitch<bool>(NaNArg->getValue())
- .Case("2008", true)
- .Case("legacy", false)
- .Default(false);
+ .Case("2008", true)
+ .Case("legacy", false)
+ .Default(false);
// NaN2008 is the default for MIPS32r6/MIPS64r6.
return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
- .Cases("mips32r6", "mips64r6", true)
- .Default(false);
+ .Cases("mips32r6", "mips64r6", true)
+ .Default(false);
return false;
}
bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName) {
+ StringRef ABIName, StringRef FloatABI) {
if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
Triple.getVendor() != llvm::Triple::MipsTechnologies)
return false;
@@ -5472,11 +5918,30 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
if (ABIName != "32")
return false;
+ // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
+ // present.
+ if (FloatABI == "soft")
+ return false;
+
return llvm::StringSwitch<bool>(CPUName)
- .Cases("mips2", "mips3", "mips4", "mips5", true)
- .Cases("mips32", "mips32r2", true)
- .Cases("mips64", "mips64r2", true)
- .Default(false);
+ .Cases("mips2", "mips3", "mips4", "mips5", true)
+ .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
+ .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
+ .Default(false);
+}
+
+bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
+ StringRef CPUName, StringRef ABIName,
+ StringRef FloatABI) {
+ bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
+
+ // FPXX shouldn't be used if -msingle-float is present.
+ if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
+ options::OPT_mdouble_float))
+ if (A->getOption().matches(options::OPT_msingle_float))
+ UseFPXX = false;
+
+ return UseFPXX;
}
llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
@@ -5493,29 +5958,29 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// translation.
return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
- .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
- .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
- .Case("ppc64", llvm::Triple::ppc64)
- .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
- .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
- llvm::Triple::x86)
- .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
- // This is derived from the driver driver.
- .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
- .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
- .Cases("armv7s", "xscale", llvm::Triple::arm)
- .Case("arm64", llvm::Triple::aarch64)
- .Case("r600", llvm::Triple::r600)
- .Case("amdgcn", llvm::Triple::amdgcn)
- .Case("nvptx", llvm::Triple::nvptx)
- .Case("nvptx64", llvm::Triple::nvptx64)
- .Case("amdil", llvm::Triple::amdil)
- .Case("spir", llvm::Triple::spir)
- .Default(llvm::Triple::UnknownArch);
+ .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
+ .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
+ .Case("ppc64", llvm::Triple::ppc64)
+ .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
+ .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
+ llvm::Triple::x86)
+ .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
+ // This is derived from the driver driver.
+ .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
+ .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
+ .Cases("armv7s", "xscale", llvm::Triple::arm)
+ .Case("arm64", llvm::Triple::aarch64)
+ .Case("r600", llvm::Triple::r600)
+ .Case("amdgcn", llvm::Triple::amdgcn)
+ .Case("nvptx", llvm::Triple::nvptx)
+ .Case("nvptx64", llvm::Triple::nvptx64)
+ .Case("amdil", llvm::Triple::amdil)
+ .Case("spir", llvm::Triple::spir)
+ .Default(llvm::Triple::UnknownArch);
}
void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
- llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
+ const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
T.setArch(Arch);
if (Str == "x86_64h")
@@ -5527,14 +5992,13 @@ void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
}
const char *Clang::getBaseInputName(const ArgList &Args,
- const InputInfoList &Inputs) {
- return Args.MakeArgString(
- llvm::sys::path::filename(Inputs[0].getBaseInput()));
+ const InputInfo &Input) {
+ return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput()));
}
const char *Clang::getBaseInputStem(const ArgList &Args,
const InputInfoList &Inputs) {
- const char *Str = getBaseInputName(Args, Inputs);
+ const char *Str = getBaseInputName(Args, Inputs[0]);
if (const char *End = strrchr(Str, '.'))
return Args.MakeArgString(std::string(Str, End));
@@ -5556,11 +6020,81 @@ const char *Clang::getDependencyFileName(const ArgList &Args,
return Args.MakeArgString(Res + ".d");
}
-void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ // CloudABI only supports static linkage.
+ CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("--gc-sections");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ const ToolChain::path_list &Paths = ToolChain.getFilePaths();
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (D.IsUsingLTO(Args))
+ AddGoldPlugin(ToolChain, Args, CmdArgs);
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX())
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lcompiler_rt");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
@@ -5609,8 +6143,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Args.hasArg(options::OPT_static)))
CmdArgs.push_back("-static");
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
assert(Output.isFilename() && "Unexpected lipo output.");
CmdArgs.push_back("-o");
@@ -5621,8 +6154,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
// asm_final spec is empty.
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
@@ -5641,7 +6173,7 @@ void darwin::MachOTool::AddMachOArch(const ArgList &Args,
CmdArgs.push_back("-force_cpusubtype_ALL");
}
-bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
+bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
// We only need to generate a temp path for LTO if we aren't compiling object
// files. When compiling source files, we run 'dsymutil' after linking. We
// don't run 'dsymutil' when compiling object files.
@@ -5652,21 +6184,19 @@ bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
return false;
}
-void darwin::Link::AddLinkArgs(Compilation &C,
- const ArgList &Args,
- ArgStringList &CmdArgs,
- const InputInfoList &Inputs) const {
+void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const {
const Driver &D = getToolChain().getDriver();
const toolchains::MachO &MachOTC = getMachOToolChain();
- unsigned Version[3] = { 0, 0, 0 };
+ unsigned Version[3] = {0, 0, 0};
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
bool HadExtra;
- if (!Driver::GetReleaseVersion(A->getValue(), Version[0],
- Version[1], Version[2], HadExtra) ||
+ if (!Driver::GetReleaseVersion(A->getValue(), Version[0], Version[1],
+ Version[2], HadExtra) ||
HadExtra)
- D.Diag(diag::err_drv_invalid_version_number)
- << A->getAsString(Args);
+ D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args);
}
// Newer linkers support -demangle. Pass it if supported and not disabled by
@@ -5677,12 +6207,18 @@ void darwin::Link::AddLinkArgs(Compilation &C,
if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
CmdArgs.push_back("-export_dynamic");
+ // If we are using App Extension restrictions, pass a flag to the linker
+ // telling it that the compiled code has been audited.
+ if (Args.hasFlag(options::OPT_fapplication_extension,
+ options::OPT_fno_application_extension, false))
+ CmdArgs.push_back("-application_extension");
+
// If we are using LTO, then automatically create a temporary file path for
// the linker to use, so that it's lifetime will extend past a possible
// dsymutil step.
if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
C.addTempFile(TmpPath);
CmdArgs.push_back("-object_path_lto");
CmdArgs.push_back(TmpPath);
@@ -5710,8 +6246,8 @@ void darwin::Link::AddLinkArgs(Compilation &C,
if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
(A = Args.getLastArg(options::OPT_current__version)) ||
(A = Args.getLastArg(options::OPT_install__name)))
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "-dynamiclib";
+ D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
+ << "-dynamiclib";
Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
@@ -5726,8 +6262,8 @@ void darwin::Link::AddLinkArgs(Compilation &C,
(A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
(A = Args.getLastArg(options::OPT_keep__private__externs)) ||
(A = Args.getLastArg(options::OPT_private__bundle)))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-dynamiclib";
+ D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
+ << "-dynamiclib";
Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
"-dylib_compatibility_version");
@@ -5765,9 +6301,9 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
- if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
- options::OPT_fno_pie,
- options::OPT_fno_PIE)) {
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
+ options::OPT_fno_pie, options::OPT_fno_PIE)) {
if (A->getOption().matches(options::OPT_fpie) ||
A->getOption().matches(options::OPT_fPIE))
CmdArgs.push_back("-pie");
@@ -5826,17 +6362,11 @@ void darwin::Link::AddLinkArgs(Compilation &C,
Args.AddLastArg(CmdArgs, options::OPT_Mach);
}
-enum LibOpenMP {
- LibUnknown,
- LibGOMP,
- LibIOMP5
-};
-
-void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
// If the number of arguments surpasses the system limits, we will encode the
@@ -5856,7 +6386,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &Arg : Args)
Arg->claim();
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("touch"));
+ Args.MakeArgString(getToolChain().GetProgramPath("touch"));
CmdArgs.push_back(Output.getFilename());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
return;
@@ -5887,29 +6417,33 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles))
getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
+ // SafeStack requires its own runtime libraries
+ // These libraries should be linked first, to make sure the
+ // __safestack_init constructor executes before everything else
+ if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
+ getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
+ "libclang_rt.safestack_osx.a",
+ /*AlwaysLink=*/true);
+ }
+
Args.AddAllArgs(CmdArgs, options::OPT_L);
- LibOpenMP UsedOpenMPLib = LibUnknown;
- if (Args.hasArg(options::OPT_fopenmp)) {
- UsedOpenMPLib = LibGOMP;
- } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
- UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
- .Case("libgomp", LibGOMP)
- .Case("libiomp5", LibIOMP5)
- .Default(LibUnknown);
- if (UsedOpenMPLib == LibUnknown)
- getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue();
- }
- switch (UsedOpenMPLib) {
- case LibGOMP:
- CmdArgs.push_back("-lgomp");
- break;
- case LibIOMP5:
- CmdArgs.push_back("-liomp5");
- break;
- case LibUnknown:
- break;
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ switch (getOpenMPRuntime(getToolChain(), Args)) {
+ case OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
}
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
@@ -5930,8 +6464,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
InputFileList.push_back(II.getFilename());
}
- if (isObjCRuntimeLinked(Args) &&
- !Args.hasArg(options::OPT_nostdlib) &&
+ if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
// We use arclite library for both ARC and subscripting support.
getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
@@ -5951,6 +6484,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fnested_functions))
CmdArgs.push_back("-allow_stack_execute");
+ // TODO: It would be nice to use addProfileRT() here, but darwin's compiler-rt
+ // paths are different enough from other toolchains that this needs a fair
+ // amount of refactoring done first.
+ getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
+
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (getToolChain().getDriver().CCCIsCXX())
@@ -5970,10 +6508,23 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_F);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetLinkerPath());
+ // -iframework should be forwarded as -F.
+ for (const Arg *A : Args.filtered(options::OPT_iframework))
+ CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
+ if (A->getValue() == StringRef("Accelerate")) {
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("Accelerate");
+ }
+ }
+ }
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
std::unique_ptr<Command> Cmd =
- llvm::make_unique<Command>(JA, *this, Exec, CmdArgs);
+ llvm::make_unique<Command>(JA, *this, Exec, CmdArgs);
Cmd->setInputFileList(std::move(InputFileList));
C.addCommand(std::move(Cmd));
}
@@ -6016,7 +6567,7 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Input.getFilename());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
+ Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
@@ -6039,11 +6590,11 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Input.getFilename());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
+ Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
@@ -6051,8 +6602,7 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -6064,16 +6614,16 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
// FIXME: Find a real GCC, don't hard-code versions here
std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
const llvm::Triple &T = getToolChain().getTriple();
std::string LibPath = "/usr/lib/";
- llvm::Triple::ArchType Arch = T.getArch();
+ const llvm::Triple::ArchType Arch = T.getArch();
switch (Arch) {
case llvm::Triple::x86:
GCCLibPath +=
@@ -6164,16 +6714,15 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
bool NeedsKPIC = false;
@@ -6191,6 +6740,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
CmdArgs.push_back("-32");
NeedsKPIC = true;
break;
@@ -6226,8 +6776,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (NeedsKPIC)
addAssemblerKPIC(Args, CmdArgs);
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -6235,16 +6784,15 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -6295,25 +6843,25 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("gcrt0.o")));
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbeginS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
}
}
std::string Triple = getToolChain().getTripleString();
if (Triple.substr(0, 6) == "x86_64")
Triple.replace(0, 6, "amd64");
- CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
- "/4.2.1"));
+ CmdArgs.push_back(
+ Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -6329,7 +6877,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
CmdArgs.push_back("-lm");
@@ -6340,18 +6888,17 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_pthread)) {
- if (!Args.hasArg(options::OPT_shared) &&
- Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lpthread_p");
+ if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
else
- CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lpthread");
}
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lc_p");
else
- CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lc");
}
CmdArgs.push_back("-lgcc");
@@ -6360,28 +6907,26 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtend.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtendS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
}
- const char *Exec =
- Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void bitrig::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -6393,11 +6938,11 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -6433,16 +6978,16 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("gcrt0.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbeginS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
}
}
@@ -6463,8 +7008,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Args.hasArg(options::OPT_pthread)) {
- if (!Args.hasArg(options::OPT_shared) &&
- Args.hasArg(options::OPT_pg))
+ if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lpthread_p");
else
CmdArgs.push_back("-lpthread");
@@ -6478,7 +7022,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
StringRef MyArch;
- switch (getToolChain().getTriple().getArch()) {
+ switch (getToolChain().getArch()) {
case llvm::Triple::arm:
MyArch = "arm";
break;
@@ -6497,23 +7041,22 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtend.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtendS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
}
- const char *Exec =
- Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -6558,7 +7101,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mfpu=softvfp");
}
- switch(getToolChain().getTriple().getEnvironment()) {
+ switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
@@ -6569,6 +7112,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-matpcs");
}
} else if (getToolChain().getArch() == llvm::Triple::sparc ||
+ getToolChain().getArch() == llvm::Triple::sparcel ||
getToolChain().getArch() == llvm::Triple::sparcv9) {
if (getToolChain().getArch() == llvm::Triple::sparc)
CmdArgs.push_back("-Av8plusa");
@@ -6578,8 +7122,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
addAssemblerKPIC(Args, CmdArgs);
}
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -6591,17 +7134,18 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const toolchains::FreeBSD& ToolChain =
- static_cast<const toolchains::FreeBSD&>(getToolChain());
+void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool IsPIE =
- !Args.hasArg(options::OPT_shared) &&
- (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ !Args.hasArg(options::OPT_shared) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -6631,7 +7175,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
- llvm::Triple::ArchType Arch = ToolChain.getArch();
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
CmdArgs.push_back("--hash-style=both");
@@ -6642,12 +7185,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct ld in the base system to link 32-bit code.
- if (ToolChain.getArch() == llvm::Triple::x86) {
+ if (Arch == llvm::Triple::x86) {
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386_fbsd");
}
- if (ToolChain.getArch() == llvm::Triple::ppc) {
+ if (Arch == llvm::Triple::ppc) {
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_fbsd");
}
@@ -6781,12 +7324,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(ToolChain, Args, CmdArgs);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
@@ -6804,7 +7346,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
- std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
+ std::string MArch = arm::getARMTargetCPU(Args, getToolChain().getTriple());
CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
break;
}
@@ -6834,6 +7376,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
CmdArgs.push_back("-32");
addAssemblerKPIC(Args, CmdArgs);
break;
@@ -6845,11 +7388,10 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
break;
default:
- break;
+ break;
}
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -6861,11 +7403,11 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -6912,7 +7454,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
+ arm::appendEBLinkFlags(
+ Args, CmdArgs,
+ llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
CmdArgs.push_back("-m");
switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::EABI:
@@ -6936,14 +7480,14 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("elf32btsmip");
else
CmdArgs.push_back("elf32ltsmip");
- } else if (mips::hasMipsAbiArg(Args, "64")) {
- CmdArgs.push_back("-m");
- if (getToolChain().getArch() == llvm::Triple::mips64)
- CmdArgs.push_back("elf64btsmip");
- else
- CmdArgs.push_back("elf64ltsmip");
- }
- break;
+ } else if (mips::hasMipsAbiArg(Args, "64")) {
+ CmdArgs.push_back("-m");
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("elf64btsmip");
+ else
+ CmdArgs.push_back("elf64ltsmip");
+ }
+ break;
case llvm::Triple::ppc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_nbsd");
@@ -6979,17 +7523,17 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crti.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crti.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbeginS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
}
}
@@ -7007,7 +7551,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;
if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) {
- switch(getToolChain().getArch()) {
+ switch (getToolChain().getArch()) {
case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -7055,13 +7599,12 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
- "crtend.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
- "crtendS.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
- "crtn.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
addProfileRT(getToolChain(), Args, CmdArgs);
@@ -7070,57 +7613,76 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
bool NeedsKPIC = false;
+ switch (getToolChain().getArch()) {
+ default:
+ break;
// Add --32/--64 to make sure we get the format we want.
// This is incomplete
- if (getToolChain().getArch() == llvm::Triple::x86) {
+ case llvm::Triple::x86:
CmdArgs.push_back("--32");
- } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+ break;
+ case llvm::Triple::x86_64:
if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
CmdArgs.push_back("--x32");
else
CmdArgs.push_back("--64");
- } else if (getToolChain().getArch() == llvm::Triple::ppc) {
+ break;
+ case llvm::Triple::ppc:
CmdArgs.push_back("-a32");
CmdArgs.push_back("-mppc");
CmdArgs.push_back("-many");
- } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
+ break;
+ case llvm::Triple::ppc64:
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-many");
- } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
+ break;
+ case llvm::Triple::ppc64le:
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-many");
CmdArgs.push_back("-mlittle-endian");
- } else if (getToolChain().getArch() == llvm::Triple::sparc) {
+ break;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
CmdArgs.push_back("-32");
CmdArgs.push_back("-Av8plusa");
NeedsKPIC = true;
- } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
+ break;
+ case llvm::Triple::sparcv9:
CmdArgs.push_back("-64");
CmdArgs.push_back("-Av9a");
NeedsKPIC = true;
- } else if (getToolChain().getArch() == llvm::Triple::arm ||
- getToolChain().getArch() == llvm::Triple::armeb) {
- StringRef MArch = getToolChain().getArchName();
- if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ switch (Triple.getSubArch()) {
+ case llvm::Triple::ARMSubArch_v7:
CmdArgs.push_back("-mfpu=neon");
- if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
- MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
+ break;
+ case llvm::Triple::ARMSubArch_v8:
CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
+ break;
+ default:
+ break;
+ }
StringRef ARMFloatABI = tools::arm::getARMFloatABI(
- getToolChain().getDriver(), Args, getToolChain().getTriple());
+ getToolChain().getDriver(), Args,
+ llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
@@ -7130,15 +7692,17 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
// march from being picked in the absence of a cpu flag.
Arg *A;
if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
- StringRef(A->getValue()) == "krait")
- CmdArgs.push_back("-march=armv7-a");
+ StringRef(A->getValue()).lower() == "krait")
+ CmdArgs.push_back("-march=armv7-a");
else
Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
- } else if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mipsel ||
- getToolChain().getArch() == llvm::Triple::mips64 ||
- getToolChain().getArch() == llvm::Triple::mips64el) {
+ break;
+ }
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
@@ -7182,18 +7746,19 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
+ StringRef MIPSFloatABI = getMipsFloatABI(getToolChain().getDriver(), Args);
if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
options::OPT_mfp64)) {
A->claim();
A->render(Args, CmdArgs);
- } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
- ABIName))
+ } else if (mips::shouldUseFPXX(Args, getToolChain().getTriple(), CPUName,
+ ABIName, MIPSFloatABI))
CmdArgs.push_back("-mfpxx");
// Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
// -mno-mips16 is actually -no-mips16.
- if (Arg *A = Args.getLastArg(options::OPT_mips16,
- options::OPT_mno_mips16)) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16)) {
if (A->getOption().matches(options::OPT_mips16)) {
A->claim();
A->render(Args, CmdArgs);
@@ -7218,22 +7783,28 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
options::OPT_msoft_float);
+ Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,
+ options::OPT_msingle_float);
+
Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
options::OPT_mno_odd_spreg);
NeedsKPIC = true;
- } else if (getToolChain().getArch() == llvm::Triple::systemz) {
+ break;
+ }
+ case llvm::Triple::systemz: {
// Always pass an -march option, since our default of z10 is later
// than the GNU assembler's default.
StringRef CPUName = getSystemZTargetCPU(Args);
CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
+ break;
+ }
}
if (NeedsKPIC)
addAssemblerKPIC(Args, CmdArgs);
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -7250,7 +7821,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs));
+ SplitDebugName(Args, Inputs[0]));
}
static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
@@ -7288,34 +7859,33 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
static std::string getLinuxDynamicLinker(const ArgList &Args,
const toolchains::Linux &ToolChain) {
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+
if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
if (ToolChain.getTriple().isArch64Bit())
return "/system/bin/linker64";
else
return "/system/bin/linker";
- } else if (ToolChain.getArch() == llvm::Triple::x86 ||
- ToolChain.getArch() == llvm::Triple::sparc)
+ } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::sparc ||
+ Arch == llvm::Triple::sparcel)
return "/lib/ld-linux.so.2";
- else if (ToolChain.getArch() == llvm::Triple::aarch64)
+ else if (Arch == llvm::Triple::aarch64)
return "/lib/ld-linux-aarch64.so.1";
- else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
+ else if (Arch == llvm::Triple::aarch64_be)
return "/lib/ld-linux-aarch64_be.so.1";
- else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb) {
+ else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
return "/lib/ld-linux-armhf.so.3";
else
return "/lib/ld-linux.so.3";
- } else if (ToolChain.getArch() == llvm::Triple::armeb ||
- ToolChain.getArch() == llvm::Triple::thumbeb) {
+ } else if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) {
+ // TODO: check which dynamic linker name.
if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
- return "/lib/ld-linux-armhf.so.3"; /* TODO: check which dynamic linker name. */
+ return "/lib/ld-linux-armhf.so.3";
else
- return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */
- } else if (ToolChain.getArch() == llvm::Triple::mips ||
- ToolChain.getArch() == llvm::Triple::mipsel ||
- ToolChain.getArch() == llvm::Triple::mips64 ||
- ToolChain.getArch() == llvm::Triple::mips64el) {
+ return "/lib/ld-linux.so.3";
+ } else if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
+ Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName);
@@ -7333,21 +7903,21 @@ static std::string getLinuxDynamicLinker(const ArgList &Args,
LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
return (LibDir + "/" + LibName).str();
- } else if (ToolChain.getArch() == llvm::Triple::ppc)
+ } else if (Arch == llvm::Triple::ppc)
return "/lib/ld.so.1";
- else if (ToolChain.getArch() == llvm::Triple::ppc64) {
+ else if (Arch == llvm::Triple::ppc64) {
if (ppc::hasPPCAbiArg(Args, "elfv2"))
return "/lib64/ld64.so.2";
return "/lib64/ld64.so.1";
- } else if (ToolChain.getArch() == llvm::Triple::ppc64le) {
+ } else if (Arch == llvm::Triple::ppc64le) {
if (ppc::hasPPCAbiArg(Args, "elfv1"))
return "/lib64/ld64.so.1";
return "/lib64/ld64.so.2";
- } else if (ToolChain.getArch() == llvm::Triple::systemz)
+ } else if (Arch == llvm::Triple::systemz)
return "/lib64/ld64.so.1";
- else if (ToolChain.getArch() == llvm::Triple::sparcv9)
+ else if (Arch == llvm::Triple::sparcv9)
return "/lib64/ld-linux.so.2";
- else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
+ else if (Arch == llvm::Triple::x86_64 &&
ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
return "/libx32/ld-linux-x32.so.2";
else
@@ -7362,7 +7932,8 @@ static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
switch (RLT) {
case ToolChain::RLT_CompilerRT:
switch (TC.getTriple().getOS()) {
- default: llvm_unreachable("unsupported OS");
+ default:
+ llvm_unreachable("unsupported OS");
case llvm::Triple::Win32:
case llvm::Triple::Linux:
addClangRT(TC, Args, CmdArgs);
@@ -7396,6 +7967,7 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::ppc64le:
return "elf64lppc";
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
return "elf32_sparc";
case llvm::Triple::sparcv9:
return "elf64_sparc";
@@ -7422,24 +7994,20 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
}
}
-void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const toolchains::Linux& ToolChain =
- static_cast<const toolchains::Linux&>(getToolChain());
+void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::Linux &ToolChain =
+ static_cast<const toolchains::Linux &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool isAndroid =
- ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
const bool IsPIE =
- !Args.hasArg(options::OPT_shared) &&
- !Args.hasArg(options::OPT_static) &&
- (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
- // On Android every code is PIC so every executable is PIE
- // Cannot use isPIEDefault here since otherwise
- // PIE only logic will be enabled during compilation
- isAndroid);
+ !Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
ArgStringList CmdArgs;
@@ -7463,9 +8031,10 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- if (ToolChain.getArch() == llvm::Triple::armeb ||
- ToolChain.getArch() == llvm::Triple::thumbeb)
- arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
+ if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
+ arm::appendEBLinkFlags(
+ Args, CmdArgs,
+ llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
for (const auto &Opt : ToolChain.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
@@ -7478,10 +8047,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args));
if (Args.hasArg(options::OPT_static)) {
- if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::armeb ||
- ToolChain.getArch() == llvm::Triple::thumb ||
- ToolChain.getArch() == llvm::Triple::thumbeb)
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
+ Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb)
CmdArgs.push_back("-Bstatic");
else
CmdArgs.push_back("-static");
@@ -7489,10 +8056,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-shared");
}
- if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::armeb ||
- ToolChain.getArch() == llvm::Triple::thumb ||
- ToolChain.getArch() == llvm::Triple::thumbeb ||
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
+ Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
@@ -7507,7 +8072,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles)) {
if (!isAndroid) {
const char *crt1 = nullptr;
- if (!Args.hasArg(options::OPT_shared)){
+ if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
else if (IsPIE)
@@ -7555,11 +8120,10 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// The profile runtime also needs access to system libraries.
addProfileRT(getToolChain(), Args, CmdArgs);
- if (D.CCCIsCXX() &&
- !Args.hasArg(options::OPT_nostdlib) &&
+ if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
- !Args.hasArg(options::OPT_static);
+ !Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bstatic");
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -7567,6 +8131,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Bdynamic");
CmdArgs.push_back("-lm");
}
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
if (!Args.hasArg(options::OPT_nostdlib)) {
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -7576,37 +8142,39 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
- LibOpenMP UsedOpenMPLib = LibUnknown;
- if (Args.hasArg(options::OPT_fopenmp)) {
- UsedOpenMPLib = LibGOMP;
- } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
- UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
- .Case("libgomp", LibGOMP)
- .Case("libiomp5", LibIOMP5)
- .Default(LibUnknown);
- if (UsedOpenMPLib == LibUnknown)
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue();
+ bool WantPthread = Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads);
+
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ // OpenMP runtimes implies pthreads when using the GNU toolchain.
+ // FIXME: Does this really make sense for all GNU toolchains?
+ WantPthread = true;
+
+ // Also link the particular OpenMP runtimes.
+ switch (getOpenMPRuntime(ToolChain, Args)) {
+ case OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+
+ // FIXME: Exclude this for platforms with libgomp that don't require
+ // librt. Most modern Linux platforms require it, but some may not.
+ CmdArgs.push_back("-lrt");
+ break;
+ case OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
}
- switch (UsedOpenMPLib) {
- case LibGOMP:
- CmdArgs.push_back("-lgomp");
- // FIXME: Exclude this for platforms with libgomp that don't require
- // librt. Most modern Linux platforms require it, but some may not.
- CmdArgs.push_back("-lrt");
- break;
- case LibIOMP5:
- CmdArgs.push_back("-liomp5");
- break;
- case LibUnknown:
- break;
- }
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
- if ((Args.hasArg(options::OPT_pthread) ||
- Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) &&
- !isAndroid)
+ if (WantPthread && !isAndroid)
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
@@ -7636,11 +8204,187 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}
-void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+// NaCl ARM assembly (inline or standalone) can be written with a set of macros
+// for the various SFI requirements like register masking. The assembly tool
+// inserts the file containing the macros as an input into all the assembly
+// jobs.
+void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::NaCl_TC &ToolChain =
+ static_cast<const toolchains::NaCl_TC &>(getToolChain());
+ InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm,
+ "nacl-arm-macros.s");
+ InputInfoList NewInputs;
+ NewInputs.push_back(NaClMacros);
+ NewInputs.append(Inputs.begin(), Inputs.end());
+ gnutools::Assembler::ConstructJob(C, JA, Output, NewInputs, Args,
+ LinkingOutput);
+}
+
+// This is quite similar to gnutools::Linker::ConstructJob with changes that
+// we use static by default, do not yet support sanitizers or LTO, and a few
+// others. Eventually we can support more of that and hopefully migrate back
+// to gnutools::Linker.
+void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ const toolchains::NaCl_TC &ToolChain =
+ static_cast<const toolchains::NaCl_TC &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool IsStatic =
+ !Args.hasArg(options::OPT_dynamic) && !Args.hasArg(options::OPT_shared);
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ // NaCl_TC doesn't have ExtraOpts like Linux; the only relevant flag from
+ // there is --build-id, which we do want.
+ CmdArgs.push_back("--build-id");
+
+ if (!IsStatic)
+ CmdArgs.push_back("--eh-frame-hdr");
+
+ CmdArgs.push_back("-m");
+ if (Arch == llvm::Triple::x86)
+ CmdArgs.push_back("elf_i386_nacl");
+ else if (Arch == llvm::Triple::arm)
+ 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";
+
+ if (IsStatic)
+ CmdArgs.push_back("-static");
+ else if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-shared");
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin;
+ if (IsStatic)
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared))
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
+
+ const ToolChain::path_list &Paths = ToolChain.getFilePaths();
+
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ bool OnlyLibstdcxxStatic =
+ Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ if (!Args.hasArg(options::OPT_nodefaultlibs)) {
+ // Always use groups, since it has no effect on dynamic libraries.
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ // NaCl's libc++ currently requires libpthread, so just always include it
+ // 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");
+ }
+
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ if (IsStatic)
+ CmdArgs.push_back("-lgcc_eh");
+ 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");
+ }
+
+ if (!Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crtend;
+ if (Args.hasArg(options::OPT_shared))
+ crtend = "crtendS.o";
+ else
+ crtend = "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ }
+
+ C.addCommand(
+ llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
+}
+
+void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -7656,11 +8400,11 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -7673,10 +8417,11 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -7703,7 +8448,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lCompilerRT-Generic");
CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
}
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
@@ -7714,11 +8459,11 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
-void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -7739,11 +8484,11 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
bool UseGCC47 = llvm::sys::fs::exists("/usr/lib/gcc47");
@@ -7784,25 +8529,24 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("gcrt1.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("gcrt1.o")));
else {
if (Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("Scrt1.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("Scrt1.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
}
}
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbeginS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -7871,13 +8615,12 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtendS.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
else
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtend.o")));
- CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtn.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
addProfileRT(getToolChain(), Args, CmdArgs);
@@ -7906,18 +8649,18 @@ static std::string FindVisualStudioExecutable(const ToolChain &TC,
return Exe;
}
-void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
const ToolChain &TC = getToolChain();
assert((Output.isFilename() || Output.isNothing()) && "invalid output");
if (Output.isFilename())
- CmdArgs.push_back(Args.MakeArgString(std::string("-out:") +
- Output.getFilename()));
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-out:") + Output.getFilename()));
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode())
@@ -7926,8 +8669,8 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!llvm::sys::Process::GetEnv("LIB")) {
// If the VC environment hasn't been configured (perhaps because the user
// did not run vcvarsall), try to build a consistent link environment. If
- // the environment variable is set however, assume the user knows what he's
- // doing.
+ // the environment variable is set however, assume the user knows what
+ // they're doing.
std::string VisualStudioDir;
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
@@ -7961,14 +8704,14 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_g_Group))
CmdArgs.push_back("-debug");
- bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
+ bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
+ options::OPT_shared);
if (DLL) {
CmdArgs.push_back(Args.MakeArgString("-dll"));
SmallString<128> ImplibName(Output.getFilename());
llvm::sys::path::replace_extension(ImplibName, "lib");
- CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
- ImplibName.str()));
+ CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}
if (TC.getSanitizerArgs().needsAsanRt()) {
@@ -7976,8 +8719,7 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
static const char *CompilerRTComponents[] = {
- "asan_dynamic",
- "asan_dynamic_runtime_thunk",
+ "asan_dynamic", "asan_dynamic_runtime_thunk",
};
for (const auto &Component : CompilerRTComponents)
CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
@@ -7985,11 +8727,11 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
// to ensure proper SEH handling.
CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
} else if (DLL) {
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
} else {
static const char *CompilerRTComponents[] = {
- "asan",
- "asan_cxx",
+ "asan", "asan_cxx",
};
for (const auto &Component : CompilerRTComponents)
CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
@@ -8048,21 +8790,21 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}
-std::unique_ptr<Command> visualstudio::Compile::GetCommand(
+std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
Compilation &C, const JobAction &JA, const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
CmdArgs.push_back("/nologo");
- CmdArgs.push_back("/c"); // Compile only.
+ CmdArgs.push_back("/c"); // Compile only.
CmdArgs.push_back("/W0"); // No warnings.
// The goal is to be able to invoke this tool correctly based on
@@ -8085,7 +8827,7 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
}
}
- // Flags for which clang-cl have an alias.
+ // Flags for which clang-cl has an alias.
// FIXME: How can we ensure this stays in sync with relevant clang-cl options?
if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
@@ -8105,7 +8847,8 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
CmdArgs.push_back("/Z7");
- std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
+ std::vector<std::string> Includes =
+ Args.getAllArgValues(options::OPT_include);
for (const auto &Include : Includes)
CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
@@ -8119,7 +8862,6 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
A->render(Args, CmdArgs);
-
// Input filename.
assert(Inputs.size() == 1);
const InputInfo &II = Inputs[0];
@@ -8132,8 +8874,8 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
// Output filename.
assert(Output.getType() == types::TY_Object);
- const char *Fo = Args.MakeArgString(std::string("/Fo") +
- Output.getFilename());
+ const char *Fo =
+ Args.MakeArgString(std::string("/Fo") + Output.getFilename());
CmdArgs.push_back(Fo);
const Driver &D = getToolChain().getDriver();
@@ -8143,15 +8885,226 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
CmdArgs);
}
+/// MinGW Tools
+void MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
+ ArgStringList CmdArgs;
+
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("--32");
+ } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+ CmdArgs.push_back("--64");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+
+ if (Args.hasArg(options::OPT_gsplit_dwarf))
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs[0]));
+}
+
+void MinGW::Linker::AddLibGCC(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ if (Args.hasArg(options::OPT_mthreads))
+ CmdArgs.push_back("-lmingwthrd");
+ CmdArgs.push_back("-lmingw32");
+ if (Args.hasArg(options::OPT_shared) ||
+ Args.hasArg(options::OPT_shared_libgcc) ||
+ !Args.hasArg(options::OPT_static_libgcc)) {
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("-lgcc");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lgcc_eh");
+ }
+ CmdArgs.push_back("-lmoldname");
+ CmdArgs.push_back("-lmingwex");
+ CmdArgs.push_back("-lmsvcrt");
+}
+
+void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &TC = getToolChain();
+ const Driver &D = TC.getDriver();
+ // const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // 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));
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ CmdArgs.push_back("-m");
+ if (TC.getArch() == llvm::Triple::x86)
+ 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");
+ CmdArgs.push_back("windows");
+ } else if (Args.hasArg(options::OPT_mconsole)) {
+ CmdArgs.push_back("--subsystem");
+ CmdArgs.push_back("console");
+ }
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-Bstatic");
+ else {
+ if (Args.hasArg(options::OPT_mdll))
+ CmdArgs.push_back("--dll");
+ else if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("--shared");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-e");
+ if (TC.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("_DllMainCRTStartup@12");
+ else
+ CmdArgs.push_back("DllMainCRTStartup");
+ CmdArgs.push_back("--enable-auto-image-base");
+ }
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ // FIXME: add -N, -n flags
+ Args.AddLastArg(CmdArgs, options::OPT_r);
+ Args.AddLastArg(CmdArgs, options::OPT_s);
+ Args.AddLastArg(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
+ } else {
+ if (Args.hasArg(options::OPT_municode))
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
+ }
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ const ToolChain::path_list Paths = TC.getFilePaths();
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs);
+
+ // TODO: Add ASan stuff here
+
+ // TODO: Add profile stuff here
+
+ if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !Args.hasArg(options::OPT_static);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ if (!Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--start-group");
+
+ if (Args.hasArg(options::OPT_fstack_protector) ||
+ Args.hasArg(options::OPT_fstack_protector_strong) ||
+ Args.hasArg(options::OPT_fstack_protector_all)) {
+ CmdArgs.push_back("-lssp_nonshared");
+ CmdArgs.push_back("-lssp");
+ }
+ if (Args.hasArg(options::OPT_fopenmp))
+ CmdArgs.push_back("-lgomp");
+
+ AddLibGCC(Args, CmdArgs);
+
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgmon");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+
+ // add system libraries
+ if (Args.hasArg(options::OPT_mwindows)) {
+ CmdArgs.push_back("-lgdi32");
+ CmdArgs.push_back("-lcomdlg32");
+ }
+ CmdArgs.push_back("-ladvapi32");
+ CmdArgs.push_back("-lshell32");
+ CmdArgs.push_back("-luser32");
+ CmdArgs.push_back("-lkernel32");
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--end-group");
+ else if (!LinkerName.equals_lower("lld"))
+ AddLibGCC(Args, CmdArgs);
+ }
+
+ if (!Args.hasArg(options::OPT_nostartfiles)) {
+ // Add crtfastmath.o if available and fast math is enabled.
+ TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
+
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
+ }
+ }
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data()));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+}
/// XCore Tools
// We pass assemble and link construction to the xcc tool.
-void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -8171,8 +9124,7 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fverbose-asm");
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
@@ -8181,11 +9133,11 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
if (Output.isFilename()) {
@@ -8198,7 +9150,9 @@ void XCore::Link::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);
@@ -8207,11 +9161,11 @@ void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void CrossWindows::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
claimNoWarnArgs(Args);
const auto &TC =
static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
@@ -8219,7 +9173,8 @@ void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec;
switch (TC.getArch()) {
- default: llvm_unreachable("unsupported architecture");
+ default:
+ llvm_unreachable("unsupported architecture");
case llvm::Triple::arm:
case llvm::Triple::thumb:
break;
@@ -8245,11 +9200,11 @@ void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const auto &TC =
static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
const llvm::Triple &T = TC.getTriple();
@@ -8278,7 +9233,8 @@ void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-m");
switch (TC.getArch()) {
- default: llvm_unreachable("unsupported architecture");
+ default:
+ llvm_unreachable("unsupported architecture");
case llvm::Triple::arm:
case llvm::Triple::thumb:
// FIXME: this is incorrect for WinCE
@@ -8295,7 +9251,8 @@ void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_shared)) {
switch (T.getArch()) {
- default: llvm_unreachable("unsupported architecture");
+ default:
+ llvm_unreachable("unsupported architecture");
case llvm::Triple::arm:
case llvm::Triple::thumb:
case llvm::Triple::x86_64:
@@ -8384,3 +9341,80 @@ void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
+
+void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
+ assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
+
+ // Append all -I, -iquote, -isystem paths.
+ Args.AddAllArgs(CmdArgs, options::OPT_clang_i_Group);
+ // These are spelled the same way in clang and moviCompile.
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+
+ CmdArgs.push_back("-DMYRIAD2");
+ CmdArgs.push_back("-mcpu=myriad2");
+ CmdArgs.push_back("-S");
+
+ // Any -O option passes through without translation. What about -Ofast ?
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ A->render(Args, CmdArgs);
+
+ if (Args.hasFlag(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections)) {
+ CmdArgs.push_back("-ffunction-sections");
+ }
+ if (Args.hasArg(options::OPT_fno_inline_functions))
+ CmdArgs.push_back("-fno-inline-functions");
+
+ CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
+
+ CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ std::string Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
+ C.addCommand(
+ llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+}
+
+void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
+ assert(Output.getType() == types::TY_Object);
+
+ CmdArgs.push_back("-no6thSlotCompression");
+ CmdArgs.push_back("-cv:myriad2"); // Chip Version ?
+ CmdArgs.push_back("-noSPrefixing");
+ CmdArgs.push_back("-a"); // Mystery option.
+ for (auto Arg : Args.filtered(options::OPT_I)) {
+ Arg->claim();
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-i:") + Arg->getValue(0)));
+ }
+ CmdArgs.push_back("-elf"); // Output format.
+ CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-o:") + Output.getFilename()));
+
+ std::string Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
+ C.addCommand(
+ llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h
index 5aea825..52ab731 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.h
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLS_H
#define LLVM_CLANG_LIB_DRIVER_TOOLS_H
+#include "clang/Basic/VersionTuple.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
@@ -31,16 +32,19 @@ namespace toolchains {
namespace tools {
namespace visualstudio {
- class Compile;
+class Compiler;
}
using llvm::opt::ArgStringList;
+SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
+ bool Shared = false);
+
/// \brief Clang compiler tool.
class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
public:
static const char *getBaseInputName(const llvm::opt::ArgList &Args,
- const InputInfoList &Inputs);
+ const InputInfo &Input);
static const char *getBaseInputStem(const llvm::opt::ArgList &Args,
const InputInfoList &Inputs);
static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
@@ -85,11 +89,14 @@ using llvm::opt::ArgStringList;
void AddClangCLArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- visualstudio::Compile *getCLFallback() const;
+ visualstudio::Compiler *getCLFallback() const;
- mutable std::unique_ptr<visualstudio::Compile> CLFallback;
+ mutable std::unique_ptr<visualstudio::Compiler> CLFallback;
public:
+ // CAUTION! The first constructor argument ("clang") is not arbitrary,
+ // as it is for other tools. Some operations on a Tool actually test
+ // whether that tool is Clang based on the Tool's Name as a string.
Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC, RF_Full) {}
bool hasGoodDiagnostics() const override { return true; }
@@ -109,7 +116,8 @@ using llvm::opt::ArgStringList;
ClangAs(const ToolChain &TC) : Tool("clang::as",
"clang integrated assembler", TC,
RF_Full) {}
-
+ void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return false; }
bool hasIntegratedCPP() const override { return false; }
@@ -122,7 +130,7 @@ using llvm::opt::ArgStringList;
/// \brief Base class for all GNU tools that provide the same behavior when
/// it comes to response files support
- class GnuTool : public Tool {
+ class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
virtual void anchor();
public:
@@ -146,14 +154,14 @@ namespace gcc {
/// RenderExtraToolArgs - Render any arguments necessary to force
/// the particular tool mode.
virtual void
- RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const = 0;
+ RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const = 0;
};
- class LLVM_LIBRARY_VISIBILITY Preprocess : public Common {
+ class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
public:
- Preprocess(const ToolChain &TC) : Common("gcc::Preprocess",
- "gcc preprocessor", TC) {}
+ Preprocessor(const ToolChain &TC)
+ : Common("gcc::Preprocessor", "gcc preprocessor", TC) {}
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedCPP() const override { return false; }
@@ -162,10 +170,10 @@ namespace gcc {
llvm::opt::ArgStringList &CmdArgs) const override;
};
- class LLVM_LIBRARY_VISIBILITY Compile : public Common {
+ class LLVM_LIBRARY_VISIBILITY Compiler : public Common {
public:
- Compile(const ToolChain &TC) : Common("gcc::Compile",
- "gcc frontend", TC) {}
+ Compiler(const ToolChain &TC)
+ : Common("gcc::Compiler", "gcc frontend", TC) {}
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
@@ -174,10 +182,10 @@ namespace gcc {
llvm::opt::ArgStringList &CmdArgs) const override;
};
- class LLVM_LIBRARY_VISIBILITY Link : public Common {
+ class LLVM_LIBRARY_VISIBILITY Linker : public Common {
public:
- Link(const ToolChain &TC) : Common("gcc::Link",
- "linker (via gcc)", TC) {}
+ Linker(const ToolChain &TC)
+ : Common("gcc::Linker", "linker (via gcc)", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -188,14 +196,15 @@ namespace gcc {
} // end namespace gcc
namespace hexagon {
- // For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile and Compile.
- // We simply use "clang -cc1" for those actions.
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("hexagon::Assemble",
- "hexagon-as", TC) {}
+// For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile
+// and Compile.
+// We simply use "clang -cc1" for those actions.
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("hexagon::Assembler", "hexagon-as", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const;
@@ -203,14 +212,13 @@ namespace hexagon {
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
- };
+};
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("hexagon::Link",
- "hexagon-ld", TC) {}
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("hexagon::Linker", "hexagon-ld", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
virtual void RenderExtraToolArgs(const JobAction &JA,
@@ -223,16 +231,23 @@ namespace hexagon {
} // end namespace hexagon.
namespace arm {
- StringRef getARMTargetCPU(const llvm::opt::ArgList &Args,
- const llvm::Triple &Triple);
+ std::string getARMTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+ const std::string getARMArch(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
const char* getARMCPUForMArch(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
- const char* getLLVMArchSuffixForARM(StringRef CPU);
+ const char* getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch);
void appendEBLinkFlags(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple);
}
namespace mips {
+ typedef enum {
+ NanLegacy = 1,
+ Nan2008 = 2
+ } NanEncoding;
+ NanEncoding getSupportedNanEncoding(StringRef &CPU);
void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, StringRef &CPUName,
StringRef &ABIName);
@@ -240,13 +255,31 @@ namespace mips {
bool isUCLibc(const llvm::opt::ArgList &Args);
bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName);
+ StringRef ABIName, StringRef FloatABI);
+ bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
+ StringRef CPUName, StringRef ABIName, StringRef FloatABI);
}
namespace ppc {
bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value);
}
+/// cloudabi -- Directly call GNU Binutils linker
+namespace cloudabi {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("cloudabi::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace cloudabi
+
namespace darwin {
llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
@@ -262,19 +295,19 @@ namespace darwin {
}
public:
- MachOTool(
- const char *Name, const char *ShortName, const ToolChain &TC,
- ResponseFileSupport ResponseSupport = RF_None,
- llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
- const char *ResponseFlag = "@")
- : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
- ResponseFlag) {}
+ MachOTool(
+ const char *Name, const char *ShortName, const ToolChain &TC,
+ ResponseFileSupport ResponseSupport = RF_None,
+ llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
+ const char *ResponseFlag = "@")
+ : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
+ ResponseFlag) {}
};
- class LLVM_LIBRARY_VISIBILITY Assemble : public MachOTool {
+ class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
public:
- Assemble(const ToolChain &TC) : MachOTool("darwin::Assemble",
- "assembler", TC) {}
+ Assembler(const ToolChain &TC)
+ : MachOTool("darwin::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -284,16 +317,16 @@ namespace darwin {
const char *LinkingOutput) const override;
};
- class LLVM_LIBRARY_VISIBILITY Link : public MachOTool {
+ class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
bool NeedsTempPath(const InputInfoList &Inputs) const;
void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const InputInfoList &Inputs) const;
public:
- Link(const ToolChain &TC) : MachOTool("darwin::Link", "linker", TC,
- RF_FileList, llvm::sys::WEM_UTF8,
- "-filelist") {}
+ Linker(const ToolChain &TC)
+ : MachOTool("darwin::Linker", "linker", TC, RF_FileList,
+ llvm::sys::WEM_UTF8, "-filelist") {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -346,27 +379,26 @@ namespace darwin {
}
- /// openbsd -- Directly call GNU Binutils assembler and linker
+/// openbsd -- Directly call GNU Binutils assembler and linker
namespace openbsd {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("openbsd::Assemble", "assembler",
- TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("openbsd::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("openbsd::Link", "linker", TC) {}
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("openbsd::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -375,26 +407,26 @@ namespace openbsd {
};
} // end namespace openbsd
- /// bitrig -- Directly call GNU Binutils assembler and linker
+/// bitrig -- Directly call GNU Binutils assembler and linker
namespace bitrig {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("bitrig::Assemble", "assembler",
- TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("bitrig::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("bitrig::Link", "linker", TC) {}
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("bitrig::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -403,26 +435,26 @@ namespace bitrig {
};
} // end namespace bitrig
- /// freebsd -- Directly call GNU Binutils assembler and linker
+/// freebsd -- Directly call GNU Binutils assembler and linker
namespace freebsd {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("freebsd::Assemble", "assembler",
- TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("freebsd::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("freebsd::Link", "linker", TC) {}
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("freebsd::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -431,29 +463,28 @@ namespace freebsd {
};
} // end namespace freebsd
- /// netbsd -- Directly call GNU Binutils assembler and linker
+/// netbsd -- Directly call GNU Binutils assembler and linker
namespace netbsd {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
- public:
- Assemble(const ToolChain &TC)
- : GnuTool("netbsd::Assemble", "assembler", TC) {}
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("netbsd::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
- public:
- Link(const ToolChain &TC)
- : GnuTool("netbsd::Link", "linker", TC) {}
+public:
+ Linker(const ToolChain &TC) : GnuTool("netbsd::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -462,13 +493,25 @@ namespace netbsd {
};
} // end namespace netbsd
- /// Directly call GNU Binutils' assembler and linker.
+/// Directly call GNU Binutils' assembler and linker.
namespace gnutools {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("GNU::Assemble", "assembler", TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC) : GnuTool("GNU::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("GNU::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -476,41 +519,53 @@ namespace gnutools {
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("GNU::Link", "linker", TC) {}
+ }
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ namespace nacltools {
+ class LLVM_LIBRARY_VISIBILITY AssemblerARM : public gnutools::Assembler {
+ public:
+ AssemblerARM(const ToolChain &TC) : gnutools::Assembler(TC) {}
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-}
- /// minix -- Directly call GNU Binutils assembler and linker
-namespace minix {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
+ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Assemble(const ToolChain &TC) : GnuTool("minix::Assemble", "assembler",
- TC) {}
+ Linker(const ToolChain &TC) : Tool("NaCl::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
};
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("minix::Link", "linker", TC) {}
+}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+/// minix -- Directly call GNU Binutils assembler and linker
+namespace minix {
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("minix::Assembler", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("minix::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -520,26 +575,26 @@ namespace minix {
};
} // end namespace minix
- /// solaris -- Directly call Solaris assembler and linker
+/// solaris -- Directly call Solaris assembler and linker
namespace solaris {
- class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
- public:
- Assemble(const ToolChain &TC) : Tool("solaris::Assemble", "assembler",
- TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+ Assembler(const ToolChain &TC)
+ : Tool("solaris::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public Tool {
- public:
- Link(const ToolChain &TC) : Tool("solaris::Link", "linker", TC) {}
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("solaris::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -548,26 +603,26 @@ namespace solaris {
};
} // end namespace solaris
- /// dragonfly -- Directly call GNU Binutils assembler and linker
+/// dragonfly -- Directly call GNU Binutils assembler and linker
namespace dragonfly {
- class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool {
- public:
- Assemble(const ToolChain &TC) : GnuTool("dragonfly::Assemble", "assembler",
- TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+public:
+ Assembler(const ToolChain &TC)
+ : GnuTool("dragonfly::Assembler", "assembler", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
- public:
- Link(const ToolChain &TC) : GnuTool("dragonfly::Link", "linker", TC) {}
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("dragonfly::Linker", "linker", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -579,26 +634,31 @@ namespace dragonfly {
/// Visual studio tools.
namespace visualstudio {
- class LLVM_LIBRARY_VISIBILITY Link : public Tool {
- public:
- Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC,
- RF_Full, llvm::sys::WEM_UTF16) {}
+VersionTuple getMSVCVersion(const Driver *D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args, bool IsWindowsMSVC);
- bool hasIntegratedCPP() const override { return false; }
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC)
+ : Tool("visualstudio::Linker", "linker", TC, RF_Full,
+ llvm::sys::WEM_UTF16) {}
+
+ bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
- };
+};
- class LLVM_LIBRARY_VISIBILITY Compile : public Tool {
- public:
- Compile(const ToolChain &TC) : Tool("visualstudio::Compile", "compiler", TC,
- RF_Full, llvm::sys::WEM_UTF16) {}
+class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
+public:
+ Compiler(const ToolChain &TC)
+ : Tool("visualstudio::Compiler", "compiler", TC, RF_Full,
+ llvm::sys::WEM_UTF16) {}
- bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
bool isLinkJob() const override { return false; }
@@ -615,45 +675,105 @@ namespace visualstudio {
};
} // end namespace visualstudio
+/// MinGW -- Directly call GNU Binutils assembler and linker
+namespace MinGW {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("MinGW::Assemble", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+private:
+ void AddLibGCC(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) const;
+};
+} // end namespace MinGW
+
namespace arm {
StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
}
namespace XCore {
- // For XCore, we do not need to instantiate tools for PreProcess, PreCompile and Compile.
- // We simply use "clang -cc1" for those actions.
- class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
- public:
- Assemble(const ToolChain &TC) : Tool("XCore::Assemble",
- "XCore-as", TC) {}
+// For XCore, we do not need to instantiate tools for PreProcess, PreCompile and
+// Compile.
+// We simply use "clang -cc1" for those actions.
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("XCore::Assembler", "XCore-as", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("XCore::Linker", "XCore-ld", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+ } // end namespace XCore.
- class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ namespace CrossWindows {
+ class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Link(const ToolChain &TC) : Tool("XCore::Link",
- "XCore-ld", TC) {}
+ Assembler(const ToolChain &TC)
+ : Tool("CrossWindows::Assembler", "as", TC) {}
bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-} // end namespace XCore.
-namespace CrossWindows {
-class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+ public:
+ Linker(const ToolChain &TC)
+ : Tool("CrossWindows::Linker", "ld", TC, RF_Full) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+}
+
+/// SHAVE tools -- Directly call moviCompile and moviAsm
+namespace SHAVE {
+class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
public:
- Assemble(const ToolChain &TC) : Tool("CrossWindows::Assemble", "as", TC) { }
+ Compiler(const ToolChain &TC) : Tool("moviCompile", "movicompile", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -661,21 +781,20 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Link(const ToolChain &TC) : Tool("CrossWindows::Link", "ld", TC, RF_Full) {}
+ Assembler(const ToolChain &TC) : Tool("moviAsm", "moviAsm", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; } // not sure.
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-}
+} // end namespace SHAVE
-} // end namespace toolchains
+} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
index 6ee764c..2085b01 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -85,7 +85,8 @@ bool types::isAcceptedByClang(ID Id) {
case TY_Asm:
case TY_C: case TY_PP_C:
case TY_CL:
- case TY_CUDA:
+ 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_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;
}
}
@@ -153,6 +166,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
.Case("cl", TY_CL)
.Case("cp", TY_CXX)
.Case("cu", TY_CUDA)
+ .Case("cui", TY_PP_CUDA)
.Case("hh", TY_CXXHeader)
.Case("ll", TY_LLVM_IR)
.Case("hpp", TY_CXXHeader)
@@ -205,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/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
index 1c66cb8..e557de9 100644
--- a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
@@ -135,7 +135,7 @@ bool EditedSource::commitInsertFromRange(SourceLocation OrigLoc,
StrVec += text;
}
- return commitInsert(OrigLoc, Offs, StrVec.str(), beforePreviousInsertions);
+ return commitInsert(OrigLoc, Offs, StrVec, beforePreviousInsertions);
}
void EditedSource::commitRemove(SourceLocation OrigLoc,
@@ -295,9 +295,11 @@ static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts,
}
if (buffer[end] == ' ') {
+ assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
+ "buffer not zero-terminated!");
if (canRemoveWhitespace(/*left=*/buffer[begin-1],
/*beforeWSpace=*/buffer[end-1],
- /*right=*/buffer[end+1],
+ /*right=*/buffer.data()[end + 1], // zero-terminated
LangOpts))
++len;
return;
@@ -360,14 +362,14 @@ void EditedSource::applyRewrites(EditsReceiver &receiver) {
continue;
}
- applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts);
+ applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts);
CurOffs = offs;
StrVec = act.Text;
CurLen = act.RemoveLen;
CurEnd = CurOffs.getWithOffset(CurLen);
}
- applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts);
+ applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts);
}
void EditedSource::clearRewrites() {
diff --git a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
index 26f1371..36a8c4d 100644
--- a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
@@ -106,7 +106,7 @@ getStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit,
Text.substr(0, Advance), UsedColumns + Chars, TabWidth, Encoding);
}
- if (Chars > MaxSplit || Text.size() == Advance)
+ if (Chars > MaxSplit || Text.size() <= Advance)
break;
if (IsBlank(Text[0]))
@@ -183,7 +183,7 @@ void BreakableStringLiteral::insertBreak(unsigned LineIndex,
}
static StringRef getLineCommentIndentPrefix(StringRef Comment) {
- static const char *const KnownPrefixes[] = { "///", "//" };
+ static const char *const KnownPrefixes[] = {"///", "//", "//!"};
StringRef LongestPrefix;
for (StringRef KnownPrefix : KnownPrefixes) {
if (Comment.startswith(KnownPrefix)) {
@@ -210,6 +210,8 @@ BreakableLineComment::BreakableLineComment(
Prefix = "// ";
else if (Prefix == "///")
Prefix = "/// ";
+ else if (Prefix == "//!")
+ Prefix = "//! ";
}
}
@@ -237,9 +239,8 @@ void BreakableLineComment::replaceWhitespace(unsigned LineIndex,
/*Spaces=*/1);
}
-void
-BreakableLineComment::replaceWhitespaceBefore(unsigned LineIndex,
- WhitespaceManager &Whitespaces) {
+void BreakableLineComment::replaceWhitespaceBefore(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) {
if (OriginalPrefix != Prefix) {
Whitespaces.replaceWhitespaceInToken(Tok, OriginalPrefix.size(), 0, "", "",
/*InPPDirective=*/false,
@@ -277,6 +278,8 @@ BreakableBlockComment::BreakableBlockComment(
// If the last line is empty, the closing "*/" will have a star.
if (i + 1 == e && Lines[i].empty())
break;
+ if (!Lines[i].empty() && i + 1 != e && Decoration.startswith(Lines[i]))
+ continue;
while (!Lines[i].startswith(Decoration))
Decoration = Decoration.substr(0, Decoration.size() - 1);
}
@@ -297,14 +300,18 @@ BreakableBlockComment::BreakableBlockComment(
}
continue;
}
+
// The first line already excludes the star.
// For all other lines, adjust the line to exclude the star and
// (optionally) the first whitespace.
- StartOfLineColumn[i] += Decoration.size();
- Lines[i] = Lines[i].substr(Decoration.size());
- LeadingWhitespace[i] += Decoration.size();
- IndentAtLineBreak =
- std::min<int>(IndentAtLineBreak, std::max(0, StartOfLineColumn[i]));
+ unsigned DecorationSize =
+ Decoration.startswith(Lines[i]) ? Lines[i].size() : Decoration.size();
+ StartOfLineColumn[i] += DecorationSize;
+ Lines[i] = Lines[i].substr(DecorationSize);
+ LeadingWhitespace[i] += DecorationSize;
+ if (!Decoration.startswith(Lines[i]))
+ IndentAtLineBreak =
+ std::min<int>(IndentAtLineBreak, std::max(0, StartOfLineColumn[i]));
}
IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size());
DEBUG({
@@ -337,7 +344,7 @@ void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
// Calculate the start of the non-whitespace text in the current line.
size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);
if (StartOfLine == StringRef::npos)
- StartOfLine = Lines[LineIndex].size();
+ StartOfLine = Lines[LineIndex].rtrim("\r\n").size();
StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);
// Adjust Lines to only contain relevant text.
@@ -407,9 +414,8 @@ void BreakableBlockComment::replaceWhitespace(unsigned LineIndex,
/*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1);
}
-void
-BreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex,
- WhitespaceManager &Whitespaces) {
+void BreakableBlockComment::replaceWhitespaceBefore(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) {
if (LineIndex == 0)
return;
StringRef Prefix = Decoration;
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
index 4cc92b0..dd56831 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
@@ -126,7 +126,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
// Don't break after very short return types (e.g. "void") as that is often
// unexpected.
if (Current.is(TT_FunctionDeclarationName) &&
- !Style.AlwaysBreakAfterDefinitionReturnType && State.Column < 6)
+ Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_None &&
+ State.Column < 6)
return false;
return !State.Stack.back().NoLineBreak;
@@ -143,33 +144,43 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true;
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
- (Style.BreakBeforeTernaryOperators &&
- (Current.is(tok::question) ||
- (Current.is(TT_ConditionalExpr) && Previous.isNot(tok::question)))) ||
+ (Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
+ Previous.isNot(tok::question)) ||
(!Style.BreakBeforeTernaryOperators &&
- (Previous.is(tok::question) || Previous.is(TT_ConditionalExpr)))) &&
+ Previous.is(TT_ConditionalExpr))) &&
State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() &&
!Current.isOneOf(tok::r_paren, tok::r_brace))
return true;
- if (Style.AlwaysBreakBeforeMultilineStrings &&
- State.Column > State.Stack.back().Indent && // Breaking saves columns.
- !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
- !Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
- nextIsMultilineString(State))
- return true;
if (((Previous.is(TT_DictLiteral) && Previous.is(tok::l_brace)) ||
Previous.is(TT_ArrayInitializerLSquare)) &&
Style.ColumnLimit > 0 &&
- getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))
+ getLengthToMatchingParen(Previous) + State.Column - 1 >
+ getColumnLimit(State))
return true;
if (Current.is(TT_CtorInitializerColon) &&
((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
return true;
+ if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound &&
+ State.Stack.back().BreakBeforeParameter)
+ return true;
- if (State.Column < getNewLineColumn(State))
+ unsigned NewLineColumn = getNewLineColumn(State);
+ if (State.Column < NewLineColumn)
return false;
- if (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None) {
+
+ if (Style.AlwaysBreakBeforeMultilineStrings &&
+ (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth ||
+ Previous.is(tok::comma) || Current.NestingLevel < 2) &&
+ !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
+ !Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
+ nextIsMultilineString(State))
+ return true;
+
+ // Using CanBreakBefore here and below takes care of the decision whether the
+ // current style uses wrapping before or after operators for the given
+ // operator.
+ if (Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
// If we need to break somewhere inside the LHS of a binary expression, we
// should also break after the operator. Otherwise, the formatting would
// hide the operator precedence, e.g. in:
@@ -185,16 +196,13 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Previous.Previous->isNot(TT_BinaryOperator); // For >>.
bool LHSIsBinaryExpr =
Previous.Previous && Previous.Previous->EndsBinaryExpression;
- if (Previous.is(TT_BinaryOperator) && (!IsComparison || LHSIsBinaryExpr) &&
- Current.isNot(TT_BinaryOperator) && // For >>.
- !Current.isTrailingComment() && !Previous.is(tok::lessless) &&
+ if ((!IsComparison || LHSIsBinaryExpr) && !Current.isTrailingComment() &&
Previous.getPrecedence() != prec::Assignment &&
State.Stack.back().BreakBeforeParameter)
return true;
- } else {
- if (Current.is(TT_BinaryOperator) && Previous.EndsBinaryExpression &&
- State.Stack.back().BreakBeforeParameter)
- return true;
+ } else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
+ State.Stack.back().BreakBeforeParameter) {
+ return true;
}
// Same as above, but for the first "<<" operator.
@@ -203,12 +211,14 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
State.Stack.back().FirstLessLess == 0)
return true;
- if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound &&
- State.Stack.back().BreakBeforeParameter)
- return true;
if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
+ // Always break after "template <...>" and leading annotations. This is only
+ // for cases where the entire line does not fit on a single line as a
+ // different LineFormatter would be used otherwise.
if (Previous.ClosesTemplateDeclaration)
return true;
+ if (Previous.is(TT_FunctionAnnotationRParen))
+ return true;
if (Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
Current.isNot(TT_LeadingJavaAnnotation))
return true;
@@ -221,8 +231,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
- (State.Stack.back().BreakBeforeParameter &&
- State.Stack.back().ContainsUnwrappedBuilder)))
+ State.Stack.back().BreakBeforeParameter))
return true;
// The following could be precomputed as they do not depend on the state.
@@ -232,6 +241,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment))
return true;
+ if (Current.is(tok::lessless) && Previous.is(tok::identifier) &&
+ Previous.TokenText == "endl")
+ return true;
+
return false;
}
@@ -245,12 +258,18 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
(Current.Previous->Tok.getIdentifierInfo() == nullptr ||
Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_not_keyword))) {
- // FIXME: Is this correct?
- int WhitespaceLength = SourceMgr.getSpellingColumnNumber(
- State.NextToken->WhitespaceRange.getEnd()) -
- SourceMgr.getSpellingColumnNumber(
- State.NextToken->WhitespaceRange.getBegin());
- State.Column += WhitespaceLength;
+ unsigned EndColumn =
+ SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getEnd());
+ if (Current.LastNewlineOffset != 0) {
+ // If there is a newline within this token, the final column will solely
+ // determined by the current end column.
+ State.Column = EndColumn;
+ } else {
+ unsigned StartColumn =
+ SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getBegin());
+ assert(EndColumn >= StartColumn);
+ State.Column += EndColumn - StartColumn;
+ }
moveStateToNextToken(State, DryRun, /*Newline=*/false);
return 0;
}
@@ -297,7 +316,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
else if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
State.Column + Spaces + Current.ColumnWidth)
State.Stack.back().ColonPos =
- State.Stack.back().Indent + Current.LongestObjCSelectorName;
+ std::max(State.FirstIndent + Style.ContinuationIndentWidth,
+ State.Stack.back().Indent) +
+ Current.LongestObjCSelectorName;
else
State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth;
}
@@ -308,9 +329,12 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
State.Stack.back().Indent = State.Column + Spaces;
if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style))
State.Stack.back().NoLineBreak = true;
- if (startsSegmentOfBuilderTypeCall(Current))
+ if (startsSegmentOfBuilderTypeCall(Current) &&
+ State.Column > getNewLineColumn(State))
State.Stack.back().ContainsUnwrappedBuilder = true;
+ if (Current.is(TT_LambdaArrow) && Style.Language == FormatStyle::LK_Java)
+ State.Stack.back().NoLineBreak = true;
if (Current.isMemberAccess() && Previous.is(tok::r_paren) &&
(Previous.MatchingParen &&
(Previous.TotalLength - Previous.MatchingParen->TotalLength > 10))) {
@@ -359,7 +383,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
const FormatToken *Next = Previous.MatchingParen->getNextNonComment();
HasTrailingCall = Next && Next->isMemberAccess();
}
- if (HasTrailingCall &&
+ if (HasTrailingCall && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].CallContinuation == 0)
State.Stack.back().LastSpace = State.Column;
}
@@ -396,7 +420,21 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
Penalty += Style.PenaltyBreakFirstLessLess;
State.Column = getNewLineColumn(State);
- State.Stack.back().NestedBlockIndent = State.Column;
+
+ // Indent nested blocks relative to this column, unless in a very specific
+ // JavaScript special case where:
+ //
+ // var loooooong_name =
+ // function() {
+ // // code
+ // }
+ //
+ // is common and should be formatted like a free-standing function.
+ if (Style.Language != FormatStyle::LK_JavaScript ||
+ Current.NestingLevel != 0 || !PreviousNonComment->is(tok::equal) ||
+ !Current.is(Keywords.kw_function))
+ State.Stack.back().NestedBlockIndent = State.Column;
+
if (NextNonComment->isMemberAccess()) {
if (State.Stack.back().CallContinuation == 0)
State.Stack.back().CallContinuation = State.Column;
@@ -406,7 +444,11 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack.back().AlignColons = false;
} else {
State.Stack.back().ColonPos =
- State.Stack.back().Indent + NextNonComment->LongestObjCSelectorName;
+ (Style.IndentWrappedFunctionNames
+ ? std::max(State.Stack.back().Indent,
+ State.FirstIndent + Style.ContinuationIndentWidth)
+ : State.Stack.back().Indent) +
+ NextNonComment->LongestObjCSelectorName;
}
} else if (State.Stack.back().AlignColons &&
State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) {
@@ -439,6 +481,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
if (NextNonComment->is(tok::question) ||
(PreviousNonComment && PreviousNonComment->is(tok::question)))
State.Stack.back().BreakBeforeParameter = true;
+ if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
+ State.Stack.back().BreakBeforeParameter = false;
if (!DryRun) {
unsigned Newlines = std::max(
@@ -458,18 +502,17 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
bool NestedBlockSpecialCase =
Current.is(tok::r_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].NestedBlockInlined;
- if (!NestedBlockSpecialCase) {
- for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ if (!NestedBlockSpecialCase)
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i)
State.Stack[i].BreakBeforeParameter = true;
- }
- }
if (PreviousNonComment &&
!PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
(PreviousNonComment->isNot(TT_TemplateCloser) ||
Current.NestingLevel != 0) &&
- !PreviousNonComment->isOneOf(TT_BinaryOperator, TT_JavaAnnotation,
- TT_LeadingJavaAnnotation) &&
+ !PreviousNonComment->isOneOf(
+ TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
+ TT_LeadingJavaAnnotation) &&
Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope())
State.Stack.back().BreakBeforeParameter = true;
@@ -516,7 +559,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
- if (Current.isOneOf(tok::r_brace, tok::r_square)) {
+ if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) {
if (Current.closesBlockTypeList(Style))
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
if (Current.MatchingParen &&
@@ -529,6 +572,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack.back().Indent;
if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
return State.StartOfStringLiteral;
+ if (NextNonComment->is(TT_ObjCStringLiteral) &&
+ State.StartOfStringLiteral != 0)
+ return State.StartOfStringLiteral - 1;
if (NextNonComment->is(tok::lessless) &&
State.Stack.back().FirstLessLess != 0)
return State.Stack.back().FirstLessLess;
@@ -546,8 +592,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack.back().VariablePos;
if ((PreviousNonComment &&
(PreviousNonComment->ClosesTemplateDeclaration ||
- PreviousNonComment->isOneOf(TT_AttributeParen, TT_JavaAnnotation,
- TT_LeadingJavaAnnotation))) ||
+ PreviousNonComment->isOneOf(
+ TT_AttributeParen, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
+ TT_LeadingJavaAnnotation))) ||
(!Style.IndentWrappedFunctionNames &&
NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName)))
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
@@ -555,7 +602,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (!State.Stack.back().ObjCSelectorNameFound) {
if (NextNonComment->LongestObjCSelectorName == 0)
return State.Stack.back().Indent;
- return State.Stack.back().Indent +
+ return (Style.IndentWrappedFunctionNames
+ ? std::max(State.Stack.back().Indent,
+ State.FirstIndent + Style.ContinuationIndentWidth)
+ : State.Stack.back().Indent) +
NextNonComment->LongestObjCSelectorName -
NextNonComment->ColumnWidth;
}
@@ -570,10 +620,16 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack.back().StartOfArraySubscripts;
return ContinuationIndent;
}
- if (NextNonComment->is(TT_StartOfName) ||
- Previous.isOneOf(tok::coloncolon, tok::equal)) {
+
+ // This ensure that we correctly format ObjC methods calls without inputs,
+ // i.e. where the last element isn't selector like: [callee method];
+ if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
+ NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr))
+ return State.Stack.back().Indent;
+
+ if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
+ Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon))
return ContinuationIndent;
- }
if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))
return ContinuationIndent;
@@ -621,7 +677,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
std::min(State.LowestLevelOnLine, Current.NestingLevel);
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
- Current.LastOperator ? 0 : State.Column + Current.ColumnWidth;
+ Current.LastOperator ? 0 : State.Column;
if (Current.is(TT_SelectorName))
State.Stack.back().ObjCSelectorNameFound = true;
if (Current.is(TT_CtorInitializerColon)) {
@@ -637,12 +693,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.Stack.back().AvoidBinPacking = true;
State.Stack.back().BreakBeforeParameter = false;
}
-
- // In ObjC method declaration we align on the ":" of parameters, but we need
- // to ensure that we indent parameters on subsequent lines by at least our
- // continuation indent width.
- if (Current.is(TT_ObjCMethodSpecifier))
- State.Stack.back().Indent += Style.ContinuationIndentWidth;
+ if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
+ State.Stack.back().NestedBlockIndent =
+ State.Column + Current.ColumnWidth + 1;
// Insert scopes created by fake parenthesis.
const FormatToken *Previous = Current.getPreviousNonComment();
@@ -653,13 +706,12 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// foo();
// bar();
// }, a, b, c);
- if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
+ if (Current.isNot(tok::comment) && Previous &&
+ Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
State.Stack.size() > 1) {
- if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline) {
- for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i)
State.Stack[i].NoLineBreak = true;
- }
- }
State.Stack[State.Stack.size() - 2].NestedBlockInlined = false;
}
if (Previous && (Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) ||
@@ -675,12 +727,13 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
moveStatePastScopeCloser(State);
moveStatePastFakeRParens(State);
- if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
+ if (Current.isStringLiteral() && State.StartOfStringLiteral == 0)
State.StartOfStringLiteral = State.Column;
- } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
- !Current.isStringLiteral()) {
+ if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
+ State.StartOfStringLiteral = State.Column + 1;
+ else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
+ !Current.isStringLiteral())
State.StartOfStringLiteral = 0;
- }
State.Column += Current.ColumnWidth;
State.NextToken = State.NextToken->Next;
@@ -712,7 +765,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
// 'return', assignments or opening <({[. The indentation for these cases
// is special cased.
bool SkipFirstExtraIndent =
- (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) ||
+ (Previous && (Previous->opensScope() ||
+ Previous->isOneOf(tok::semi, tok::kw_return) ||
(Previous->getPrecedence() == prec::Assignment &&
Style.AlignOperands) ||
Previous->is(TT_ObjCMethodExpr)));
@@ -762,7 +816,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
// ParameterToInnerFunction));
if (*I > prec::Unknown)
NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
- if (*I != prec::Conditional)
+ if (*I != prec::Conditional && !Current.is(TT_UnaryOperator))
NewParenState.StartOfFunctionCall = State.Column;
// Always indent conditional expressions. Never indent expression where
@@ -783,7 +837,6 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
for (unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
unsigned VariablePos = State.Stack.back().VariablePos;
- assert(State.Stack.size() > 1);
if (State.Stack.size() == 1) {
// Do not pop the last element.
break;
@@ -806,8 +859,11 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
unsigned NewIndent;
unsigned NewIndentLevel = State.Stack.back().IndentLevel;
+ 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;
@@ -815,17 +871,30 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
++NewIndentLevel;
} else {
NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
- NewIndent = std::min(State.Column + 1, NewIndent);
}
const FormatToken *NextNoComment = Current.getNextNonComment();
AvoidBinPacking =
Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) ||
- Style.Language == FormatStyle::LK_Proto || !Style.BinPackParameters ||
+ 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,
State.Stack.back().StartOfFunctionCall);
+
+ // Ensure that different different brackets force relative alignment, e.g.:
+ // void SomeFunction(vector< // break
+ // int> v);
+ // FIXME: We likely want to do this for more combinations of brackets.
+ // Verify that it is wanted for ObjC, too.
+ if (Current.Tok.getKind() == tok::less &&
+ Current.ParentBracket == tok::l_paren) {
+ NewIndent = std::max(NewIndent, State.Stack.back().Indent);
+ LastSpace = std::max(LastSpace, State.Stack.back().Indent);
+ }
+
AvoidBinPacking =
(State.Line->MustBeDeclaration && !Style.BinPackParameters) ||
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
@@ -833,19 +902,31 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
(Current.PackingKind == PPK_OnePerLine ||
(!BinPackInconclusiveFunctions &&
Current.PackingKind == PPK_Inconclusive)));
- // If this '[' opens an ObjC call, determine whether all parameters fit
- // into one line and put one per line if they don't.
- if (Current.is(TT_ObjCMethodExpr) && Style.ColumnLimit != 0 &&
- getLengthToMatchingParen(Current) + State.Column >
+ if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) {
+ if (Style.ColumnLimit) {
+ // If this '[' opens an ObjC call, determine whether all parameters fit
+ // into one line and put one per line if they don't.
+ if (getLengthToMatchingParen(Current) + State.Column >
getColumnLimit(State))
- BreakBeforeParameter = true;
+ BreakBeforeParameter = true;
+ } else {
+ // For ColumnLimit = 0, we have to figure out whether there is or has to
+ // be a line break within this call.
+ for (const FormatToken *Tok = &Current;
+ Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
+ if (Tok->MustBreakBefore ||
+ (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
+ BreakBeforeParameter = true;
+ break;
+ }
+ }
+ }
+ }
}
bool NoLineBreak = State.Stack.back().NoLineBreak ||
(Current.is(TT_TemplateOpener) &&
State.Stack.back().ContainsUnwrappedBuilder);
- unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
- State.Stack.push_back(ParenState(NewIndent, NewIndentLevel,
- State.Stack.back().LastSpace,
+ State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace,
AvoidBinPacking, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
@@ -1082,8 +1163,9 @@ bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
if (Current.getNextNonComment() &&
Current.getNextNonComment()->isStringLiteral())
return true; // Implicit concatenation.
- if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
- Style.ColumnLimit)
+ if (Style.ColumnLimit != 0 &&
+ State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
+ Style.ColumnLimit)
return true; // String will be split.
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
index 36691d9..9b9154e 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
@@ -148,13 +148,10 @@ struct ParenState {
ParenState(unsigned Indent, unsigned IndentLevel, unsigned LastSpace,
bool AvoidBinPacking, bool NoLineBreak)
: Indent(Indent), IndentLevel(IndentLevel), LastSpace(LastSpace),
- NestedBlockIndent(Indent), FirstLessLess(0),
- BreakBeforeClosingBrace(false), QuestionColumn(0),
+ NestedBlockIndent(Indent), BreakBeforeClosingBrace(false),
AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
- NoLineBreak(NoLineBreak), LastOperatorWrapped(true), ColonPos(0),
- StartOfFunctionCall(0), StartOfArraySubscripts(0),
- NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
- ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
+ NoLineBreak(NoLineBreak), LastOperatorWrapped(true),
+ ContainsLineBreak(false), ContainsUnwrappedBuilder(false),
AlignColons(true), ObjCSelectorNameFound(false),
HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
@@ -180,90 +177,90 @@ struct ParenState {
///
/// Used to align "<<" operators. 0 if no such operator has been encountered
/// on a level.
- unsigned FirstLessLess;
-
- /// \brief Whether a newline needs to be inserted before the block's closing
- /// brace.
- ///
- /// We only want to insert a newline before the closing brace if there also
- /// was a newline after the beginning left brace.
- bool BreakBeforeClosingBrace;
+ unsigned FirstLessLess = 0;
/// \brief The column of a \c ? in a conditional expression;
- unsigned QuestionColumn;
-
- /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
- /// lines, in this context.
- bool AvoidBinPacking;
-
- /// \brief Break after the next comma (or all the commas in this context if
- /// \c AvoidBinPacking is \c true).
- bool BreakBeforeParameter;
-
- /// \brief Line breaking in this context would break a formatting rule.
- bool NoLineBreak;
-
- /// \brief True if the last binary operator on this level was wrapped to the
- /// next line.
- bool LastOperatorWrapped;
+ unsigned QuestionColumn = 0;
/// \brief The position of the colon in an ObjC method declaration/call.
- unsigned ColonPos;
+ unsigned ColonPos = 0;
/// \brief The start of the most recent function in a builder-type call.
- unsigned StartOfFunctionCall;
+ unsigned StartOfFunctionCall = 0;
/// \brief Contains the start of array subscript expressions, so that they
/// can be aligned.
- unsigned StartOfArraySubscripts;
+ unsigned StartOfArraySubscripts = 0;
/// \brief If a nested name specifier was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
- unsigned NestedNameSpecifierContinuation;
+ unsigned NestedNameSpecifierContinuation = 0;
/// \brief If a call expression was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
- unsigned CallContinuation;
+ unsigned CallContinuation = 0;
/// \brief The column of the first variable name in a variable declaration.
///
/// Used to align further variables if necessary.
- unsigned VariablePos;
+ unsigned VariablePos = 0;
+
+ /// \brief Whether a newline needs to be inserted before the block's closing
+ /// brace.
+ ///
+ /// We only want to insert a newline before the closing brace if there also
+ /// was a newline after the beginning left brace.
+ bool BreakBeforeClosingBrace : 1;
+
+ /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
+ /// lines, in this context.
+ bool AvoidBinPacking : 1;
+
+ /// \brief Break after the next comma (or all the commas in this context if
+ /// \c AvoidBinPacking is \c true).
+ bool BreakBeforeParameter : 1;
+
+ /// \brief Line breaking in this context would break a formatting rule.
+ bool NoLineBreak : 1;
+
+ /// \brief True if the last binary operator on this level was wrapped to the
+ /// next line.
+ bool LastOperatorWrapped : 1;
/// \brief \c true if this \c ParenState already contains a line-break.
///
/// The first line break in a certain \c ParenState causes extra penalty so
/// that clang-format prefers similar breaks, i.e. breaks in the same
/// parenthesis.
- bool ContainsLineBreak;
+ bool ContainsLineBreak : 1;
/// \brief \c true if this \c ParenState contains multiple segments of a
/// builder-type call on one line.
- bool ContainsUnwrappedBuilder;
+ bool ContainsUnwrappedBuilder : 1;
/// \brief \c true if the colons of the curren ObjC method expression should
/// be aligned.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool AlignColons;
+ bool AlignColons : 1;
/// \brief \c true if at least one selector name was found in the current
/// ObjC method expression.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool ObjCSelectorNameFound;
+ bool ObjCSelectorNameFound : 1;
/// \brief \c true if there are multiple nested blocks inside these parens.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool HasMultipleNestedBlocks;
+ bool HasMultipleNestedBlocks : 1;
// \brief The start of a nested block (e.g. lambda introducer in C++ or
// "function" in JavaScript) is not wrapped to a new line.
- bool NestedBlockInlined;
+ bool NestedBlockInlined : 1;
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
@@ -297,11 +294,11 @@ struct ParenState {
if (VariablePos != Other.VariablePos)
return VariablePos < Other.VariablePos;
if (ContainsLineBreak != Other.ContainsLineBreak)
- return ContainsLineBreak < Other.ContainsLineBreak;
+ return ContainsLineBreak;
if (ContainsUnwrappedBuilder != Other.ContainsUnwrappedBuilder)
- return ContainsUnwrappedBuilder < Other.ContainsUnwrappedBuilder;
+ return ContainsUnwrappedBuilder;
if (NestedBlockInlined != Other.NestedBlockInlined)
- return NestedBlockInlined < Other.NestedBlockInlined;
+ return NestedBlockInlined;
return false;
}
};
diff --git a/contrib/llvm/tools/clang/lib/Format/Format.cpp b/contrib/llvm/tools/clang/lib/Format/Format.cpp
index 2a4721f..382ae81 100644
--- a/contrib/llvm/tools/clang/lib/Format/Format.cpp
+++ b/contrib/llvm/tools/clang/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,12 +94,25 @@ 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);
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
+ static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
+ IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
+ IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
+ IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
static void enumeration(IO &IO,
@@ -109,10 +123,8 @@ struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
}
};
-template <>
-struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
- static void enumeration(IO &IO,
- FormatStyle::PointerAlignmentStyle &Value) {
+template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
@@ -144,8 +156,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("Language", Style.Language);
if (IO.outputting()) {
- StringRef StylesArray[] = { "LLVM", "Google", "Chromium",
- "Mozilla", "WebKit", "GNU" };
+ StringRef StylesArray[] = {"LLVM", "Google", "Chromium",
+ "Mozilla", "WebKit", "GNU"};
ArrayRef<StringRef> Styles(StylesArray);
for (size_t i = 0, e = Styles.size(); i < e; ++i) {
StringRef StyleName(Styles[i]);
@@ -171,8 +183,20 @@ template <> struct MappingTraits<FormatStyle> {
}
}
+ // For backward compatibility.
+ if (!IO.outputting()) {
+ IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
+ IO.mapOptional("IndentFunctionDeclarationAfterType",
+ Style.IndentWrappedFunctionNames);
+ IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
+ IO.mapOptional("SpaceAfterControlStatementKeyword",
+ Style.SpaceBeforeParens);
+ }
+
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
+ IO.mapOptional("AlignConsecutiveAssignments",
+ Style.AlignConsecutiveAssignments);
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -182,42 +206,49 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowShortBlocksOnASingleLine);
IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
Style.AllowShortCaseLabelsOnASingleLine);
+ IO.mapOptional("AllowShortFunctionsOnASingleLine",
+ Style.AllowShortFunctionsOnASingleLine);
IO.mapOptional("AllowShortIfStatementsOnASingleLine",
Style.AllowShortIfStatementsOnASingleLine);
IO.mapOptional("AllowShortLoopsOnASingleLine",
Style.AllowShortLoopsOnASingleLine);
- IO.mapOptional("AllowShortFunctionsOnASingleLine",
- Style.AllowShortFunctionsOnASingleLine);
IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
Style.AlwaysBreakAfterDefinitionReturnType);
- IO.mapOptional("AlwaysBreakTemplateDeclarations",
- Style.AlwaysBreakTemplateDeclarations);
IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
Style.AlwaysBreakBeforeMultilineStrings);
+ IO.mapOptional("AlwaysBreakTemplateDeclarations",
+ Style.AlwaysBreakTemplateDeclarations);
+ IO.mapOptional("BinPackArguments", Style.BinPackArguments);
+ IO.mapOptional("BinPackParameters", Style.BinPackParameters);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
+ IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
IO.mapOptional("BreakConstructorInitializersBeforeComma",
Style.BreakConstructorInitializersBeforeComma);
- IO.mapOptional("BinPackParameters", Style.BinPackParameters);
- IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
+ IO.mapOptional("CommentPragmas", Style.CommentPragmas);
IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
IO.mapOptional("ConstructorInitializerIndentWidth",
Style.ConstructorInitializerIndentWidth);
+ IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
+ IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
+ IO.mapOptional("DisableFormat", Style.DisableFormat);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
+ IO.mapOptional("ForEachMacros", Style.ForEachMacros);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
- IO.mapOptional("IndentFunctionDeclarationAfterType",
- Style.IndentWrappedFunctionNames);
- IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
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);
IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
@@ -226,45 +257,30 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
Style.PenaltyBreakBeforeFirstCallParameter);
IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
- IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
IO.mapOptional("PenaltyBreakFirstLessLess",
Style.PenaltyBreakFirstLessLess);
+ IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
+ IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
+ IO.mapOptional("SpaceBeforeAssignmentOperators",
+ Style.SpaceBeforeAssignmentOperators);
+ IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
+ IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
- IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
- IO.mapOptional("Standard", Style.Standard);
- IO.mapOptional("IndentWidth", Style.IndentWidth);
- IO.mapOptional("TabWidth", Style.TabWidth);
- IO.mapOptional("UseTab", Style.UseTab);
- IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
- IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
- IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
- IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
- IO.mapOptional("SpacesInCStyleCastParentheses",
- Style.SpacesInCStyleCastParentheses);
- IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
IO.mapOptional("SpacesInContainerLiterals",
Style.SpacesInContainerLiterals);
- IO.mapOptional("SpaceBeforeAssignmentOperators",
- Style.SpaceBeforeAssignmentOperators);
- IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
- IO.mapOptional("CommentPragmas", Style.CommentPragmas);
- IO.mapOptional("ForEachMacros", Style.ForEachMacros);
-
- // For backward compatibility.
- if (!IO.outputting()) {
- IO.mapOptional("SpaceAfterControlStatementKeyword",
- Style.SpaceBeforeParens);
- IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
- IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
- }
- IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
- IO.mapOptional("DisableFormat", Style.DisableFormat);
+ IO.mapOptional("SpacesInCStyleCastParentheses",
+ Style.SpacesInCStyleCastParentheses);
+ IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
+ IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
+ IO.mapOptional("Standard", Style.Standard);
+ IO.mapOptional("TabWidth", Style.TabWidth);
+ IO.mapOptional("UseTab", Style.UseTab);
}
};
@@ -273,7 +289,7 @@ template <> struct MappingTraits<FormatStyle> {
// will be used to get default values for missing keys.
// If the first element has no Language specified, it will be treated as the
// default one for the following elements.
-template <> struct DocumentListTraits<std::vector<FormatStyle> > {
+template <> struct DocumentListTraits<std::vector<FormatStyle>> {
static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
return Seq.size();
}
@@ -331,13 +347,14 @@ FormatStyle getLLVMStyle() {
LLVMStyle.AlignAfterOpenBracket = true;
LLVMStyle.AlignOperands = true;
LLVMStyle.AlignTrailingComments = true;
+ LLVMStyle.AlignConsecutiveAssignments = false;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortBlocksOnASingleLine = false;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
- LLVMStyle.AlwaysBreakAfterDefinitionReturnType = false;
+ LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AlwaysBreakTemplateDeclarations = false;
LLVMStyle.BinPackParameters = true;
@@ -455,21 +472,28 @@ 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;
}
FormatStyle getMozillaStyle() {
FormatStyle MozillaStyle = getLLVMStyle();
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
+ MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+ MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
+ FormatStyle::DRTBS_TopLevel;
+ MozillaStyle.AlwaysBreakTemplateDeclarations = true;
+ MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
+ MozillaStyle.BreakConstructorInitializersBeforeComma = true;
+ MozillaStyle.ConstructorInitializerIndentWidth = 2;
+ MozillaStyle.ContinuationIndentWidth = 2;
MozillaStyle.Cpp11BracedListStyle = false;
- MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
- MozillaStyle.DerivePointerAlignment = true;
MozillaStyle.IndentCaseLabels = true;
MozillaStyle.ObjCSpaceAfterProperty = true;
MozillaStyle.ObjCSpaceBeforeProtocolList = false;
MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
- MozillaStyle.Standard = FormatStyle::LS_Cpp03;
return MozillaStyle;
}
@@ -495,7 +519,7 @@ FormatStyle getWebKitStyle() {
FormatStyle getGNUStyle() {
FormatStyle Style = getLLVMStyle();
- Style.AlwaysBreakAfterDefinitionReturnType = true;
+ Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_GNU;
Style.BreakBeforeTernaryOperators = true;
@@ -600,10 +624,12 @@ public:
FormatTokenLexer(SourceManager &SourceMgr, FileID ID, FormatStyle &Style,
encoding::Encoding Encoding)
: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
- Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
- Style(Style), IdentTable(getFormattingLangOpts(Style)),
- Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
- FormattingDisabled(false) {
+ LessStashed(false), Column(0), TrailingWhitespace(0),
+ SourceMgr(SourceMgr), ID(ID), Style(Style),
+ IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
+ 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);
@@ -619,7 +645,7 @@ public:
do {
Tokens.push_back(getNextToken());
tryMergePreviousTokens();
- if (Tokens.back()->NewlinesBefore > 0)
+ if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
FirstInLineIndex = Tokens.size() - 1;
} while (Tokens.back()->Tok.isNot(tok::eof));
return Tokens;
@@ -633,32 +659,62 @@ private:
return;
if (tryMergeConflictMarkers())
return;
+ if (tryMergeLessLess())
+ return;
if (Style.Language == FormatStyle::LK_JavaScript) {
if (tryMergeJSRegexLiteral())
return;
if (tryMergeEscapeSequence())
return;
+ if (tryMergeTemplateString())
+ return;
- static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
- static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
- static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
- tok::greaterequal };
- static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
- // FIXME: We probably need to change token type to mimic operator with the
- // correct priority.
- if (tryMergeTokens(JSIdentity))
+ static const tok::TokenKind JSIdentity[] = {tok::equalequal, tok::equal};
+ static const tok::TokenKind JSNotIdentity[] = {tok::exclaimequal,
+ tok::equal};
+ static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater,
+ tok::greaterequal};
+ static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
+ // FIXME: Investigate what token type gives the correct operator priority.
+ if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSNotIdentity))
+ if (tryMergeTokens(JSNotIdentity, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSShiftEqual))
+ if (tryMergeTokens(JSShiftEqual, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSRightArrow))
+ if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
return;
}
}
- bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
+ bool tryMergeLessLess() {
+ // Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
+ if (Tokens.size() < 3)
+ return false;
+
+ bool FourthTokenIsLess = false;
+ if (Tokens.size() > 3)
+ FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less);
+
+ auto First = Tokens.end() - 3;
+ if (First[2]->is(tok::less) || First[1]->isNot(tok::less) ||
+ First[0]->isNot(tok::less) || FourthTokenIsLess)
+ return false;
+
+ // Only merge if there currently is no whitespace between the two "<".
+ if (First[1]->WhitespaceRange.getBegin() !=
+ First[1]->WhitespaceRange.getEnd())
+ return false;
+
+ First[0]->Tok.setKind(tok::lessless);
+ First[0]->TokenText = "<<";
+ First[0]->ColumnWidth += 1;
+ Tokens.erase(Tokens.end() - 2);
+ return true;
+ }
+
+ bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType) {
if (Tokens.size() < Kinds.size())
return false;
@@ -668,8 +724,9 @@ private:
return false;
unsigned AddLength = 0;
for (unsigned i = 1; i < Kinds.size(); ++i) {
- if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
- First[i]->WhitespaceRange.getEnd())
+ if (!First[i]->is(Kinds[i]) ||
+ First[i]->WhitespaceRange.getBegin() !=
+ First[i]->WhitespaceRange.getEnd())
return false;
AddLength += First[i]->TokenText.size();
}
@@ -677,6 +734,7 @@ private:
First[0]->TokenText = StringRef(First[0]->TokenText.data(),
First[0]->TokenText.size() + AddLength);
First[0]->ColumnWidth += AddLength;
+ First[0]->Type = NewType;
return true;
}
@@ -705,35 +763,62 @@ private:
bool tryMergeJSRegexLiteral() {
if (Tokens.size() < 2)
return false;
+
+ // If this is a string literal with a slash inside, compute the slash's
+ // offset and try to find the beginning of the regex literal.
+ // Also look at tok::unknown, as it can be an unterminated char literal.
+ size_t SlashInStringPos = StringRef::npos;
+ if (Tokens.back()->isOneOf(tok::string_literal, tok::char_constant,
+ tok::unknown)) {
+ // Start search from position 1 as otherwise, this is an unknown token
+ // for an unterminated /*-comment which is handled elsewhere.
+ SlashInStringPos = Tokens.back()->TokenText.find('/', 1);
+ if (SlashInStringPos == StringRef::npos)
+ return false;
+ }
+
// If a regex literal ends in "\//", this gets represented by an unknown
// token "\" and a comment.
bool MightEndWithEscapedSlash =
Tokens.back()->is(tok::comment) &&
Tokens.back()->TokenText.startswith("//") &&
Tokens[Tokens.size() - 2]->TokenText == "\\";
- if (!MightEndWithEscapedSlash &&
+ if (!MightEndWithEscapedSlash && SlashInStringPos == StringRef::npos &&
(Tokens.back()->isNot(tok::slash) ||
(Tokens[Tokens.size() - 2]->is(tok::unknown) &&
Tokens[Tokens.size() - 2]->TokenText == "\\")))
return false;
+
unsigned TokenCount = 0;
- unsigned LastColumn = Tokens.back()->OriginalColumn;
for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
++TokenCount;
- if (I[0]->is(tok::slash) && I + 1 != E &&
- (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
- tok::exclaim, tok::l_square, tok::colon, tok::comma,
- tok::question, tok::kw_return) ||
- I[1]->isBinaryOperator())) {
+ auto Prev = I + 1;
+ while (Prev != E && Prev[0]->is(tok::comment))
+ ++Prev;
+ if (I[0]->isOneOf(tok::slash, tok::slashequal) &&
+ (Prev == E ||
+ ((Prev[0]->isOneOf(tok::l_paren, tok::semi, tok::l_brace,
+ tok::r_brace, tok::exclaim, tok::l_square,
+ tok::colon, tok::comma, tok::question,
+ tok::kw_return) ||
+ Prev[0]->isBinaryOperator())))) {
+ unsigned LastColumn = Tokens.back()->OriginalColumn;
+ SourceLocation Loc = Tokens.back()->Tok.getLocation();
if (MightEndWithEscapedSlash) {
// This regex literal ends in '\//'. Skip past the '//' of the last
// token and re-start lexing from there.
- SourceLocation Loc = Tokens.back()->Tok.getLocation();
resetLexer(SourceMgr.getFileOffset(Loc) + 2);
+ } else if (SlashInStringPos != StringRef::npos) {
+ // This regex literal ends in a string_literal with a slash inside.
+ // Calculate end column and reset lexer appropriately.
+ resetLexer(SourceMgr.getFileOffset(Loc) + SlashInStringPos + 1);
+ LastColumn += SlashInStringPos;
}
Tokens.resize(Tokens.size() - TokenCount);
Tokens.back()->Tok.setKind(tok::unknown);
Tokens.back()->Type = TT_RegexLiteral;
+ // Treat regex literals like other string_literals.
+ Tokens.back()->Tok.setKind(tok::string_literal);
Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
return true;
}
@@ -745,6 +830,94 @@ private:
return false;
}
+ bool tryMergeTemplateString() {
+ if (Tokens.size() < 2)
+ return false;
+
+ FormatToken *EndBacktick = Tokens.back();
+ // Backticks get lexed as tok::unknown tokens. If a template string contains
+ // a comment start, it gets lexed as a tok::comment, or tok::unknown if
+ // unterminated.
+ if (!EndBacktick->isOneOf(tok::comment, tok::string_literal,
+ tok::char_constant, tok::unknown))
+ return false;
+ size_t CommentBacktickPos = EndBacktick->TokenText.find('`');
+ // Unknown token that's not actually a backtick, or a comment that doesn't
+ // contain a backtick.
+ if (CommentBacktickPos == StringRef::npos)
+ return false;
+
+ unsigned TokenCount = 0;
+ bool IsMultiline = false;
+ unsigned EndColumnInFirstLine =
+ EndBacktick->OriginalColumn + EndBacktick->ColumnWidth;
+ for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; I++) {
+ ++TokenCount;
+ if (I[0]->IsMultiline)
+ IsMultiline = true;
+
+ // If there was a preceding template string, this must be the start of a
+ // template string, not the end.
+ if (I[0]->is(TT_TemplateString))
+ return false;
+
+ if (I[0]->isNot(tok::unknown) || I[0]->TokenText != "`") {
+ // Keep track of the rhs offset of the last token to wrap across lines -
+ // its the rhs offset of the first line of the template string, used to
+ // determine its width.
+ if (I[0]->IsMultiline)
+ EndColumnInFirstLine = I[0]->OriginalColumn + I[0]->ColumnWidth;
+ // If the token has newlines, the token before it (if it exists) is the
+ // rhs end of the previous line.
+ if (I[0]->NewlinesBefore > 0 && (I + 1 != E)) {
+ EndColumnInFirstLine = I[1]->OriginalColumn + I[1]->ColumnWidth;
+ IsMultiline = true;
+ }
+ continue;
+ }
+
+ Tokens.resize(Tokens.size() - TokenCount);
+ Tokens.back()->Type = TT_TemplateString;
+ const char *EndOffset =
+ EndBacktick->TokenText.data() + 1 + CommentBacktickPos;
+ if (CommentBacktickPos != 0) {
+ // If the backtick was not the first character (e.g. in a comment),
+ // re-lex after the backtick position.
+ SourceLocation Loc = EndBacktick->Tok.getLocation();
+ resetLexer(SourceMgr.getFileOffset(Loc) + CommentBacktickPos + 1);
+ }
+ Tokens.back()->TokenText =
+ StringRef(Tokens.back()->TokenText.data(),
+ EndOffset - Tokens.back()->TokenText.data());
+
+ unsigned EndOriginalColumn = EndBacktick->OriginalColumn;
+ if (EndOriginalColumn == 0) {
+ SourceLocation Loc = EndBacktick->Tok.getLocation();
+ EndOriginalColumn = SourceMgr.getSpellingColumnNumber(Loc);
+ }
+ // If the ` is further down within the token (e.g. in a comment).
+ EndOriginalColumn += CommentBacktickPos;
+
+ if (IsMultiline) {
+ // ColumnWidth is from backtick to last token in line.
+ // LastLineColumnWidth is 0 to backtick.
+ // x = `some content
+ // until here`;
+ Tokens.back()->ColumnWidth =
+ EndColumnInFirstLine - Tokens.back()->OriginalColumn;
+ // +1 for the ` itself.
+ Tokens.back()->LastLineColumnWidth = EndOriginalColumn + 1;
+ Tokens.back()->IsMultiline = true;
+ } else {
+ // Token simply spans from start to end, +1 for the ` itself.
+ Tokens.back()->ColumnWidth =
+ EndOriginalColumn - Tokens.back()->OriginalColumn + 1;
+ }
+ return true;
+ }
+ return false;
+ }
+
bool tryMerge_TMacro() {
if (Tokens.size() < 4)
return false;
@@ -772,6 +945,8 @@ private:
String->OriginalColumn = Macro->OriginalColumn;
String->ColumnWidth = encoding::columnWidthWithTabs(
String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding);
+ String->NewlinesBefore = Macro->NewlinesBefore;
+ String->HasUnescapedNewline = Macro->HasUnescapedNewline;
Tokens.pop_back();
Tokens.pop_back();
@@ -842,21 +1017,33 @@ private:
return false;
}
+ FormatToken *getStashedToken() {
+ // Create a synthesized second '>' or '<' token.
+ Token Tok = FormatTok->Tok;
+ StringRef TokenText = FormatTok->TokenText;
+
+ unsigned OriginalColumn = FormatTok->OriginalColumn;
+ FormatTok = new (Allocator.Allocate()) FormatToken;
+ FormatTok->Tok = Tok;
+ SourceLocation TokLocation =
+ FormatTok->Tok.getLocation().getLocWithOffset(Tok.getLength() - 1);
+ FormatTok->Tok.setLocation(TokLocation);
+ FormatTok->WhitespaceRange = SourceRange(TokLocation, TokLocation);
+ FormatTok->TokenText = TokenText;
+ FormatTok->ColumnWidth = 1;
+ FormatTok->OriginalColumn = OriginalColumn + 1;
+
+ return FormatTok;
+ }
+
FormatToken *getNextToken() {
if (GreaterStashed) {
- // Create a synthesized second '>' token.
- // FIXME: Increment Column and set OriginalColumn.
- Token Greater = FormatTok->Tok;
- FormatTok = new (Allocator.Allocate()) FormatToken;
- FormatTok->Tok = Greater;
- SourceLocation GreaterLocation =
- FormatTok->Tok.getLocation().getLocWithOffset(1);
- FormatTok->WhitespaceRange =
- SourceRange(GreaterLocation, GreaterLocation);
- FormatTok->TokenText = ">";
- FormatTok->ColumnWidth = 1;
GreaterStashed = false;
- return FormatTok;
+ return getStashedToken();
+ }
+ if (LessStashed) {
+ LessStashed = false;
+ return getStashedToken();
}
FormatTok = new (Allocator.Allocate()) FormatToken;
@@ -869,20 +1056,32 @@ private:
// Consume and record whitespace until we find a significant token.
unsigned WhitespaceLength = TrailingWhitespace;
while (FormatTok->Tok.is(tok::unknown)) {
- for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) {
- switch (FormatTok->TokenText[i]) {
+ StringRef Text = FormatTok->TokenText;
+ auto EscapesNewline = [&](int pos) {
+ // A '\r' here is just part of '\r\n'. Skip it.
+ if (pos >= 0 && Text[pos] == '\r')
+ --pos;
+ // See whether there is an odd number of '\' before this.
+ unsigned count = 0;
+ for (; pos >= 0; --pos, ++count)
+ if (Text[pos] != '\\')
+ break;
+ return count & 1;
+ };
+ // FIXME: This miscounts tok:unknown tokens that are not just
+ // whitespace, e.g. a '`' character.
+ for (int i = 0, e = Text.size(); i != e; ++i) {
+ switch (Text[i]) {
case '\n':
++FormatTok->NewlinesBefore;
- // FIXME: This is technically incorrect, as it could also
- // be a literal backslash at the end of the line.
- if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' &&
- (FormatTok->TokenText[i - 1] != '\r' || i == 1 ||
- FormatTok->TokenText[i - 2] != '\\')))
- FormatTok->HasUnescapedNewline = true;
+ FormatTok->HasUnescapedNewline = !EscapesNewline(i - 1);
FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
Column = 0;
break;
case '\r':
+ FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
+ Column = 0;
+ break;
case '\f':
case '\v':
Column = 0;
@@ -894,13 +1093,11 @@ private:
Column += Style.TabWidth - Column % Style.TabWidth;
break;
case '\\':
- if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' &&
- FormatTok->TokenText[i + 1] != '\n'))
+ if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n'))
FormatTok->Type = TT_ImplicitStringLiteral;
break;
default:
FormatTok->Type = TT_ImplicitStringLiteral;
- ++Column;
break;
}
}
@@ -920,6 +1117,7 @@ private:
FormatTok->TokenText[1] == '\n') {
++FormatTok->NewlinesBefore;
WhitespaceLength += 2;
+ FormatTok->LastNewlineOffset = 2;
Column = 0;
FormatTok->TokenText = FormatTok->TokenText.substr(2);
}
@@ -948,6 +1146,10 @@ private:
FormatTok->Tok.setKind(tok::greater);
FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
GreaterStashed = true;
+ } else if (FormatTok->Tok.is(tok::lessless)) {
+ FormatTok->Tok.setKind(tok::less);
+ FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
+ LessStashed = true;
}
// Now FormatTok is the next non-whitespace token.
@@ -975,16 +1177,28 @@ private:
Column = FormatTok->LastLineColumnWidth;
}
- FormatTok->IsForEachMacro =
- std::binary_search(ForEachMacros.begin(), ForEachMacros.end(),
- FormatTok->Tok.getIdentifierInfo());
+ 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;
}
FormatToken *FormatTok;
bool IsFirstToken;
- bool GreaterStashed;
+ bool GreaterStashed, LessStashed;
unsigned Column;
unsigned TrailingWhitespace;
std::unique_ptr<Lexer> Lex;
@@ -1002,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()),
@@ -1037,6 +1254,7 @@ private:
getFormattingLangOpts(Style), Buffer.begin(),
Buffer.begin() + Offset, Buffer.end()));
Lex->SetKeepWhitespaceMode(true);
+ TrailingWhitespace = 0;
}
};
@@ -1072,13 +1290,13 @@ public:
<< "\n");
}
- tooling::Replacements format() {
+ tooling::Replacements format(bool *IncompleteFormat) {
tooling::Replacements Result;
FormatTokenLexer Tokens(SourceMgr, ID, Style, Encoding);
UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(),
*this);
- bool StructuralError = Parser.parse();
+ Parser.parse();
assert(UnwrappedLines.rbegin()->empty());
for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
++Run) {
@@ -1088,7 +1306,7 @@ public:
AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
}
tooling::Replacements RunResult =
- format(AnnotatedLines, StructuralError, Tokens);
+ format(AnnotatedLines, Tokens, IncompleteFormat);
DEBUG({
llvm::dbgs() << "Replacements for run " << Run << ":\n";
for (tooling::Replacements::iterator I = RunResult.begin(),
@@ -1107,7 +1325,8 @@ public:
}
tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- bool StructuralError, FormatTokenLexer &Tokens) {
+ FormatTokenLexer &Tokens,
+ bool *IncompleteFormat) {
TokenAnnotator Annotator(Style, Tokens.getKeywords());
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Annotator.annotate(*AnnotatedLines[i]);
@@ -1122,8 +1341,9 @@ public:
ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,
Whitespaces, Encoding,
BinPackInconclusiveFunctions);
- UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
- Formatter.format(AnnotatedLines, /*DryRun=*/false);
+ UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
+ IncompleteFormat)
+ .format(AnnotatedLines);
return Whitespaces.generateReplacements();
}
@@ -1340,27 +1560,19 @@ private:
} // end anonymous namespace
-tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
- SourceManager &SourceMgr,
- ArrayRef<CharSourceRange> Ranges) {
- if (Style.DisableFormat)
- return tooling::Replacements();
- return reformat(Style, SourceMgr,
- SourceMgr.getFileID(Lex.getSourceLocation()), Ranges);
-}
-
tooling::Replacements reformat(const FormatStyle &Style,
SourceManager &SourceMgr, FileID ID,
- ArrayRef<CharSourceRange> Ranges) {
+ ArrayRef<CharSourceRange> Ranges,
+ bool *IncompleteFormat) {
if (Style.DisableFormat)
return tooling::Replacements();
Formatter formatter(Style, SourceMgr, ID, Ranges);
- return formatter.format();
+ return formatter.format(IncompleteFormat);
}
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
- StringRef FileName) {
+ StringRef FileName, bool *IncompleteFormat) {
if (Style.DisableFormat)
return tooling::Replacements();
@@ -1383,7 +1595,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
SourceLocation End = Start.getLocWithOffset(Range.getLength());
CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
}
- return reformat(Style, SourceMgr, ID, CharRanges);
+ return reformat(Style, SourceMgr, ID, CharRanges, IncompleteFormat);
}
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
@@ -1392,12 +1604,12 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.LineComment = 1;
- bool AlternativeOperators = Style.Language != FormatStyle::LK_JavaScript &&
- Style.Language != FormatStyle::LK_Java;
+ bool AlternativeOperators = Style.Language == FormatStyle::LK_Cpp;
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
LangOpts.Bool = 1;
LangOpts.ObjC1 = 1;
LangOpts.ObjC2 = 1;
+ LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
return LangOpts;
}
@@ -1415,7 +1627,8 @@ const char *StyleOptionHelpDescription =
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.endswith(".java")) {
return FormatStyle::LK_Java;
- } else if (FileName.endswith_lower(".js")) {
+ } else if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts")) {
+ // JavaScript or TypeScript.
return FormatStyle::LK_JavaScript;
} else if (FileName.endswith_lower(".proto") ||
FileName.endswith_lower(".protodevel")) {
@@ -1498,8 +1711,6 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName,
return Style;
}
}
- llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle
- << " style\n";
if (!UnsuitableConfigFiles.empty()) {
llvm::errs() << "Configuration file(s) do(es) not support "
<< getLanguageName(Style.Language) << ": "
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
index badb3a3..6c244c3 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
@@ -18,10 +18,25 @@
#include "clang/Format/Format.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Debug.h"
+#include <climits>
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 {
@@ -59,12 +74,13 @@ void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {}
unsigned CommaSeparatedList::formatAfterToken(LineState &State,
ContinuationIndenter *Indenter,
bool DryRun) {
- if (!State.NextToken->Previous || !State.NextToken->Previous->Previous)
+ if (State.NextToken == nullptr || !State.NextToken->Previous)
return 0;
// Ensure that we start on the opening brace.
- const FormatToken *LBrace = State.NextToken->Previous->Previous;
- if (LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block ||
+ const FormatToken *LBrace =
+ State.NextToken->Previous->getPreviousNonComment();
+ if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block ||
LBrace->Type == TT_DictLiteral ||
LBrace->Next->Type == TT_DesignatedInitializerPeriod)
return 0;
@@ -132,9 +148,9 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
return;
// In C++11 braced list style, we should not format in columns unless they
- // have many items (20 or more) or we allow bin-packing of function
- // parameters.
- if (Style.Cpp11BracedListStyle && !Style.BinPackParameters &&
+ // have many items (20 or more) or we allow bin-packing of function call
+ // arguments.
+ if (Style.Cpp11BracedListStyle && !Style.BinPackArguments &&
Commas.size() < 19)
return;
@@ -143,19 +159,21 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
return;
FormatToken *ItemBegin = Token->Next;
+ while (ItemBegin->isTrailingComment())
+ ItemBegin = ItemBegin->Next;
SmallVector<bool, 8> MustBreakBeforeItem;
// The lengths of an item if it is put at the end of the line. This includes
// trailing comments which are otherwise ignored for column alignment.
SmallVector<unsigned, 8> EndOfLineItemLength;
- unsigned MinItemLength = Style.ColumnLimit;
- unsigned MaxItemLength = 0;
-
+ bool HasSeparatingComment = false;
for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) {
// Skip comments on their own line.
- while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment())
+ while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) {
ItemBegin = ItemBegin->Next;
+ HasSeparatingComment = i > 0;
+ }
MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
if (ItemBegin->is(tok::l_brace))
@@ -178,8 +196,6 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
ItemEnd = Commas[i];
// The comma is counted as part of the item when calculating the length.
ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd));
- MinItemLength = std::min(MinItemLength, ItemLengths.back());
- MaxItemLength = std::max(MaxItemLength, ItemLengths.back());
// Consume trailing comments so the are included in EndOfLineItemLength.
if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline &&
@@ -194,20 +210,21 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
ItemBegin = ItemEnd->Next;
}
- // If this doesn't have a nested list, we require at least 6 elements in order
- // create a column layout. If it has a nested list, column layout ensures one
- // list element per line. If the difference between the shortest and longest
- // element is too large, column layout would create too much whitespace.
- if (HasNestedBracedList || Commas.size() < 5 || Token->NestingLevel != 0 ||
- MaxItemLength - MinItemLength > 10)
+ // Don't use column layout for nested lists, lists with few elements and in
+ // presence of separating comments.
+ if (Token->NestingLevel != 0 || Commas.size() < 5 || HasSeparatingComment)
return;
// We can never place more than ColumnLimit / 3 items in a row (because of the
// spaces and the comma).
- for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) {
+ unsigned MaxItems = Style.ColumnLimit / 3;
+ std::vector<unsigned> MinSizeInColumn;
+ MinSizeInColumn.reserve(MaxItems);
+ for (unsigned Columns = 1; Columns <= MaxItems; ++Columns) {
ColumnFormat Format;
Format.Columns = Columns;
Format.ColumnSizes.resize(Columns);
+ MinSizeInColumn.assign(Columns, UINT_MAX);
Format.LineCount = 1;
bool HasRowWithSufficientColumns = false;
unsigned Column = 0;
@@ -219,9 +236,10 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
}
if (Column == Columns - 1)
HasRowWithSufficientColumns = true;
- unsigned length =
+ unsigned Length =
(Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i];
- Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length);
+ Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], Length);
+ MinSizeInColumn[Column] = std::min(MinSizeInColumn[Column], Length);
++Column;
}
// If all rows are terminated early (e.g. by trailing comments), we don't
@@ -229,9 +247,19 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
if (!HasRowWithSufficientColumns)
break;
Format.TotalWidth = Columns - 1; // Width of the N-1 spaces.
- for (unsigned i = 0; i < Columns; ++i) {
+
+ for (unsigned i = 0; i < Columns; ++i)
Format.TotalWidth += Format.ColumnSizes[i];
- }
+
+ // Don't use this Format, if the difference between the longest and shortest
+ // element in a column exceeds a threshold to avoid excessive spaces.
+ if ([&] {
+ for (unsigned i = 0; i < Columns - 1; ++i)
+ if (Format.ColumnSizes[i] - MinSizeInColumn[i] > 10)
+ return true;
+ return false;
+ }())
+ continue;
// Ignore layouts that are bound to violate the column limit.
if (Format.TotalWidth > Style.ColumnLimit)
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.h b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
index 4811e02..f335eda 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
@@ -25,76 +25,84 @@
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_FunctionDeclarationName,
- TT_FunctionLBrace,
- TT_FunctionTypeLParen,
- TT_ImplicitStringLiteral,
- TT_InheritanceColon,
- TT_InlineASMColon,
- TT_JavaAnnotation,
- TT_LambdaArrow,
- TT_LambdaLSquare,
- TT_LeadingJavaAnnotation,
- TT_LineComment,
- TT_ObjCBlockLBrace,
- TT_ObjCBlockLParen,
- TT_ObjCDecl,
- TT_ObjCForIn,
- TT_ObjCMethodExpr,
- TT_ObjCMethodSpecifier,
- TT_ObjCProperty,
- TT_OverloadedOperator,
- TT_OverloadedOperatorLParen,
- TT_PointerOrReference,
- TT_PureVirtualSpecifier,
- TT_RangeBasedForLoopColon,
- TT_RegexLiteral,
- TT_SelectorName,
- TT_StartOfName,
- TT_TemplateCloser,
- TT_TemplateOpener,
- 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
-};
+enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };
// The packing kind of a function's parameters.
-enum ParameterPackingKind {
- PPK_BinPacked,
- PPK_OnePerLine,
- PPK_Inconclusive
-};
+enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };
-enum FormatDecision {
- FD_Unformatted,
- FD_Continue,
- FD_Break
-};
+enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };
class TokenRole;
class AnnotatedLine;
@@ -102,21 +110,7 @@ class AnnotatedLine;
/// \brief A wrapper around a \c Token storing information about the
/// whitespace characters preceding it.
struct FormatToken {
- FormatToken()
- : NewlinesBefore(0), HasUnescapedNewline(false), LastNewlineOffset(0),
- ColumnWidth(0), LastLineColumnWidth(0), IsMultiline(false),
- IsFirst(false), MustBreakBefore(false), IsUnterminatedLiteral(false),
- BlockKind(BK_Unknown), Type(TT_Unknown), SpacesRequiredBefore(0),
- CanBreakBefore(false), ClosesTemplateDeclaration(false),
- ParameterCount(0), BlockParameterCount(0),
- PackingKind(PPK_Inconclusive), TotalLength(0), UnbreakableTailLength(0),
- BindingStrength(0), NestingLevel(0), SplitPenalty(0),
- LongestObjCSelectorName(0), FakeRParens(0),
- StartsBinaryExpression(false), EndsBinaryExpression(false),
- OperatorIndex(0), LastOperator(false),
- PartOfMultiVariableDeclStmt(false), IsForEachMacro(false),
- MatchingParen(nullptr), Previous(nullptr), Next(nullptr),
- Decision(FD_Unformatted), Finalized(false) {}
+ FormatToken() {}
/// \brief The \c Token.
Token Tok;
@@ -125,48 +119,39 @@ struct FormatToken {
///
/// This can be used to determine what the user wrote in the original code
/// and thereby e.g. leave an empty line between two function definitions.
- unsigned NewlinesBefore;
+ unsigned NewlinesBefore = 0;
/// \brief Whether there is at least one unescaped newline before the \c
/// Token.
- bool HasUnescapedNewline;
+ bool HasUnescapedNewline = false;
/// \brief The range of the whitespace immediately preceding the \c Token.
SourceRange WhitespaceRange;
/// \brief The offset just past the last '\n' in this token's leading
/// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
- unsigned LastNewlineOffset;
+ unsigned LastNewlineOffset = 0;
/// \brief The width of the non-whitespace parts of the token (or its first
/// line for multi-line tokens) in columns.
/// We need this to correctly measure number of columns a token spans.
- unsigned ColumnWidth;
+ unsigned ColumnWidth = 0;
/// \brief Contains the width in columns of the last line of a multi-line
/// token.
- unsigned LastLineColumnWidth;
+ unsigned LastLineColumnWidth = 0;
/// \brief Whether the token text contains newlines (escaped or not).
- bool IsMultiline;
+ bool IsMultiline = false;
/// \brief Indicates that this is the first token.
- bool IsFirst;
+ bool IsFirst = false;
/// \brief Whether there must be a line break before this token.
///
/// This happens for example when a preprocessor directive ended directly
/// before the token.
- bool MustBreakBefore;
-
- /// \brief Returns actual token start location without leading escaped
- /// newlines and whitespace.
- ///
- /// This can be different to Tok.getLocation(), which includes leading escaped
- /// newlines.
- SourceLocation getStartOfNonWhitespace() const {
- return WhitespaceRange.getEnd();
- }
+ bool MustBreakBefore = false;
/// \brief The raw text of the token.
///
@@ -175,69 +160,74 @@ struct FormatToken {
StringRef TokenText;
/// \brief Set to \c true if this token is an unterminated literal.
- bool IsUnterminatedLiteral;
+ bool IsUnterminatedLiteral = 0;
/// \brief Contains the kind of block if this token is a brace.
- BraceBlockKind BlockKind;
+ BraceBlockKind BlockKind = BK_Unknown;
- TokenType Type;
+ TokenType Type = TT_Unknown;
/// \brief The number of spaces that should be inserted before this token.
- unsigned SpacesRequiredBefore;
+ unsigned SpacesRequiredBefore = 0;
/// \brief \c true if it is allowed to break before this token.
- bool CanBreakBefore;
+ bool CanBreakBefore = false;
- bool ClosesTemplateDeclaration;
+ /// \brief \c true if this is the ">" of "template<..>".
+ bool ClosesTemplateDeclaration = false;
/// \brief Number of parameters, if this is "(", "[" or "<".
///
/// This is initialized to 1 as we don't need to distinguish functions with
/// 0 parameters from functions with 1 parameter. Thus, we can simply count
/// the number of commas.
- unsigned ParameterCount;
+ unsigned ParameterCount = 0;
/// \brief Number of parameters that are nested blocks,
/// if this is "(", "[" or "<".
- unsigned BlockParameterCount;
+ unsigned BlockParameterCount = 0;
+
+ /// \brief If this is a bracket ("<", "(", "[" or "{"), contains the kind of
+ /// the surrounding bracket.
+ tok::TokenKind ParentBracket = tok::unknown;
/// \brief A token can have a special role that can carry extra information
/// about the token's formatting.
std::unique_ptr<TokenRole> Role;
/// \brief If this is an opening parenthesis, how are the parameters packed?
- ParameterPackingKind PackingKind;
+ ParameterPackingKind PackingKind = PPK_Inconclusive;
/// \brief The total length of the unwrapped line up to and including this
/// token.
- unsigned TotalLength;
+ unsigned TotalLength = 0;
/// \brief The original 0-based column of this token, including expanded tabs.
/// The configured TabWidth is used as tab width.
- unsigned OriginalColumn;
+ unsigned OriginalColumn = 0;
/// \brief The length of following tokens until the next natural split point,
/// or the next token that can be broken.
- unsigned UnbreakableTailLength;
+ unsigned UnbreakableTailLength = 0;
// FIXME: Come up with a 'cleaner' concept.
/// \brief The binding strength of a token. This is a combined value of
/// operator precedence, parenthesis nesting, etc.
- unsigned BindingStrength;
+ unsigned BindingStrength = 0;
/// \brief The nesting level of this token, i.e. the number of surrounding (),
/// [], {} or <>.
- unsigned NestingLevel;
+ unsigned NestingLevel = 0;
/// \brief Penalty for inserting a line break before this token.
- unsigned SplitPenalty;
+ unsigned SplitPenalty = 0;
/// \brief If this is the first ObjC selector name in an ObjC method
/// definition or call, this contains the length of the longest name.
///
/// This being set to 0 means that the selectors should not be colon-aligned,
/// e.g. because several of them are block-type.
- unsigned LongestObjCSelectorName;
+ unsigned LongestObjCSelectorName = 0;
/// \brief Stores the number of required fake parentheses and the
/// corresponding operator precedence.
@@ -246,29 +236,47 @@ struct FormatToken {
/// reverse order, i.e. inner fake parenthesis first.
SmallVector<prec::Level, 4> FakeLParens;
/// \brief Insert this many fake ) after this token for correct indentation.
- unsigned FakeRParens;
+ unsigned FakeRParens = 0;
/// \brief \c true if this token starts a binary expression, i.e. has at least
/// one fake l_paren with a precedence greater than prec::Unknown.
- bool StartsBinaryExpression;
+ bool StartsBinaryExpression = false;
/// \brief \c true if this token ends a binary expression.
- bool EndsBinaryExpression;
+ bool EndsBinaryExpression = false;
/// \brief Is this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, contains the 0-based operator index.
- unsigned OperatorIndex;
+ unsigned OperatorIndex = 0;
/// \brief Is this the last operator (or "."/"->") in a sequence of operators
/// with the same precedence?
- bool LastOperator;
+ bool LastOperator = false;
/// \brief Is this token part of a \c DeclStmt defining multiple variables?
///
/// Only set if \c Type == \c TT_StartOfName.
- bool PartOfMultiVariableDeclStmt;
+ bool PartOfMultiVariableDeclStmt = false;
+
+ /// \brief If this is a bracket, this points to the matching one.
+ FormatToken *MatchingParen = nullptr;
+
+ /// \brief The previous token in the unwrapped line.
+ FormatToken *Previous = nullptr;
- /// \brief Is this a foreach macro?
- bool IsForEachMacro;
+ /// \brief The next token in the unwrapped line.
+ FormatToken *Next = nullptr;
+
+ /// \brief If this token starts a block, this contains all the unwrapped lines
+ /// in it.
+ SmallVector<AnnotatedLine *, 1> Children;
+
+ /// \brief Stores the formatting decision for the token once it was made.
+ FormatDecision Decision = FD_Unformatted;
+
+ /// \brief If \c true, this token has been fully formatted (indented and
+ /// potentially re-formatted inside), and we do not allow further formatting
+ /// changes.
+ bool Finalized = false;
bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
bool is(TokenType TT) const { return Type == TT; }
@@ -278,27 +286,10 @@ struct FormatToken {
template <typename A, typename B> bool isOneOf(A K1, B K2) const {
return is(K1) || is(K2);
}
- template <typename A, typename B, typename C>
- bool isOneOf(A K1, B K2, C K3) const {
- return is(K1) || is(K2) || is(K3);
- }
- template <typename A, typename B, typename C, typename D>
- bool isOneOf(A K1, B K2, C K3, D K4) const {
- return is(K1) || is(K2) || is(K3) || is(K4);
+ template <typename A, typename B, typename... Ts>
+ bool isOneOf(A K1, B K2, Ts... Ks) const {
+ return is(K1) || isOneOf(K2, Ks...);
}
- template <typename A, typename B, typename C, typename D, typename E>
- bool isOneOf(A K1, B K2, C K3, D K4, E K5) const {
- return is(K1) || is(K2) || is(K3) || is(K4) || is(K5);
- }
- template <typename T>
- bool isOneOf(T K1, T K2, T K3, T K4, T K5, T K6, T K7 = tok::NUM_TOKENS,
- T K8 = tok::NUM_TOKENS, T K9 = tok::NUM_TOKENS,
- T K10 = tok::NUM_TOKENS, T K11 = tok::NUM_TOKENS,
- T K12 = tok::NUM_TOKENS) const {
- return is(K1) || is(K2) || is(K3) || is(K4) || is(K5) || is(K6) || is(K7) ||
- is(K8) || is(K9) || is(K10) || is(K11) || is(K12);
- }
-
template <typename T> bool isNot(T Kind) const { return !is(Kind); }
bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }
@@ -336,7 +327,8 @@ struct FormatToken {
/// \brief Returns \c true if this is a "." or "->" accessing a member.
bool isMemberAccess() const {
return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&
- !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow);
+ !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,
+ TT_LambdaArrow);
}
bool isUnaryOperator() const {
@@ -385,6 +377,15 @@ struct FormatToken {
}
}
+ /// \brief Returns actual token start location without leading escaped
+ /// newlines and whitespace.
+ ///
+ /// This can be different to Tok.getLocation(), which includes leading escaped
+ /// newlines.
+ SourceLocation getStartOfNonWhitespace() const {
+ return WhitespaceRange.getEnd();
+ }
+
prec::Level getPrecedence() const {
return getBinOpPrecedence(Tok.getKind(), true, true);
}
@@ -419,25 +420,10 @@ struct FormatToken {
return MatchingParen && MatchingParen->opensBlockTypeList(Style);
}
- FormatToken *MatchingParen;
-
- FormatToken *Previous;
- FormatToken *Next;
-
- SmallVector<AnnotatedLine *, 1> Children;
-
- /// \brief Stores the formatting decision for the token once it was made.
- FormatDecision Decision;
-
- /// \brief If \c true, this token has been fully formatted (indented and
- /// potentially re-formatted inside), and we do not allow further formatting
- /// changes.
- bool Finalized;
-
private:
// Disallow copying.
- FormatToken(const FormatToken &) LLVM_DELETED_FUNCTION;
- void operator=(const FormatToken &) LLVM_DELETED_FUNCTION;
+ FormatToken(const FormatToken &) = delete;
+ void operator=(const FormatToken &) = delete;
};
class ContinuationIndenter;
@@ -543,6 +529,7 @@ struct AdditionalKeywords {
kw_finally = &IdentTable.get("finally");
kw_function = &IdentTable.get("function");
+ kw_import = &IdentTable.get("import");
kw_var = &IdentTable.get("var");
kw_abstract = &IdentTable.get("abstract");
@@ -555,24 +542,33 @@ struct AdditionalKeywords {
kw_package = &IdentTable.get("package");
kw_synchronized = &IdentTable.get("synchronized");
kw_throws = &IdentTable.get("throws");
+ kw___except = &IdentTable.get("__except");
+
+ kw_mark = &IdentTable.get("mark");
kw_option = &IdentTable.get("option");
kw_optional = &IdentTable.get("optional");
kw_repeated = &IdentTable.get("repeated");
kw_required = &IdentTable.get("required");
kw_returns = &IdentTable.get("returns");
+
+ kw_signals = &IdentTable.get("signals");
+ kw_slots = &IdentTable.get("slots");
+ kw_qslots = &IdentTable.get("Q_SLOTS");
}
- // ObjC context sensitive keywords.
+ // Context sensitive keywords.
IdentifierInfo *kw_in;
IdentifierInfo *kw_CF_ENUM;
IdentifierInfo *kw_CF_OPTIONS;
IdentifierInfo *kw_NS_ENUM;
IdentifierInfo *kw_NS_OPTIONS;
+ IdentifierInfo *kw___except;
// JavaScript keywords.
IdentifierInfo *kw_finally;
IdentifierInfo *kw_function;
+ IdentifierInfo *kw_import;
IdentifierInfo *kw_var;
// Java keywords.
@@ -587,12 +583,20 @@ struct AdditionalKeywords {
IdentifierInfo *kw_synchronized;
IdentifierInfo *kw_throws;
+ // Pragma keywords.
+ IdentifierInfo *kw_mark;
+
// Proto keywords.
IdentifierInfo *kw_option;
IdentifierInfo *kw_optional;
IdentifierInfo *kw_repeated;
IdentifierInfo *kw_required;
IdentifierInfo *kw_returns;
+
+ // QT keywords.
+ IdentifierInfo *kw_signals;
+ IdentifierInfo *kw_slots;
+ IdentifierInfo *kw_qslots;
};
} // namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
index 4ba3f91..ea8b30d 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
@@ -15,6 +15,7 @@
#include "TokenAnnotator.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "format-token-annotator"
@@ -43,8 +44,14 @@ private:
bool parseAngle() {
if (!CurrentToken)
return false;
- ScopedContextCreator ContextCreator(*this, tok::less, 10);
FormatToken *Left = CurrentToken->Previous;
+ Left->ParentBracket = Contexts.back().ContextKind;
+ ScopedContextCreator ContextCreator(*this, tok::less, 10);
+
+ // If this angle is in the context of an expression, we need to be more
+ // hesitant to detect it as opening template parameters.
+ bool InExprContext = Contexts.back().IsExpression;
+
Contexts.back().IsExpression = false;
// If there's a template keyword before the opening angle bracket, this is a
// template parameter, not an argument.
@@ -68,8 +75,8 @@ private:
next();
continue;
}
- if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
- tok::colon, tok::question))
+ if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
+ (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext))
return false;
// If a && or || is found and interpreted as a binary operator, this set
// of angles is likely part of something like "a < b && c > d". If the
@@ -80,7 +87,7 @@ private:
if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
CurrentToken->Previous->is(TT_BinaryOperator) &&
Contexts[Contexts.size() - 2].IsExpression &&
- Line.First->isNot(tok::kw_template))
+ !Line.startsWith(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
@@ -92,6 +99,8 @@ private:
bool parseParens(bool LookForDecls = false) {
if (!CurrentToken)
return false;
+ FormatToken *Left = CurrentToken->Previous;
+ Left->ParentBracket = Contexts.back().ContextKind;
ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
// FIXME: This is a bit of a hack. Do better.
@@ -99,7 +108,6 @@ private:
Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
bool StartsObjCMethodExpr = false;
- FormatToken *Left = CurrentToken->Previous;
if (CurrentToken->is(tok::caret)) {
// (^ can start a block type.
Left->Type = TT_ObjCBlockLParen;
@@ -117,22 +125,22 @@ private:
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
- } else if (Line.InPPDirective &&
- (!Left->Previous ||
- !Left->Previous->isOneOf(tok::identifier,
- TT_OverloadedOperator))) {
- Contexts.back().IsExpression = true;
} else if (Left->Previous && Left->Previous->is(tok::r_square) &&
Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->is(TT_LambdaLSquare)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
+ } else if (Line.InPPDirective &&
+ (!Left->Previous ||
+ !Left->Previous->isOneOf(tok::identifier,
+ TT_OverloadedOperator))) {
+ Contexts.back().IsExpression = true;
} else if (Contexts[Contexts.size() - 2].CaretFound) {
// This is the parameter list of an ObjC block.
Contexts.back().IsExpression = false;
} else if (Left->Previous && Left->Previous->is(tok::kw___attribute)) {
Left->Type = TT_AttributeParen;
- } else if (Left->Previous && Left->Previous->IsForEachMacro) {
+ } else if (Left->Previous && Left->Previous->is(TT_ForEachMacro)) {
// The first argument to a foreach macro is a declaration.
Contexts.back().IsForEachMacro = true;
Contexts.back().IsExpression = false;
@@ -149,6 +157,8 @@ private:
bool MightBeFunctionType = CurrentToken->is(tok::star);
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
+ bool MightBeObjCForRangeLoop =
+ Left->Previous && Left->Previous->is(tok::kw_for);
while (CurrentToken) {
// LookForDecls is set when "if (" has been seen. Check for
// 'identifier' '*' 'identifier' followed by not '=' -- this
@@ -210,7 +220,8 @@ private:
}
if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
return false;
- else if (CurrentToken->is(tok::l_brace))
+
+ if (CurrentToken->is(tok::l_brace))
Left->Type = TT_Unknown; // Not TT_ObjCBlockLParen
if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
!CurrentToken->Next->HasUnescapedNewline &&
@@ -219,6 +230,15 @@ private:
if (CurrentToken->isOneOf(tok::kw_const, tok::kw_auto) ||
CurrentToken->isSimpleTypeSpecifier())
Contexts.back().IsExpression = false;
+ if (CurrentToken->isOneOf(tok::semi, tok::colon))
+ MightBeObjCForRangeLoop = false;
+ if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in))
+ CurrentToken->Type = TT_ObjCForIn;
+ // When we discover a 'new', we set CanBeExpression to 'false' in order to
+ // parse the type correctly. Reset that after a comma.
+ if (CurrentToken->is(tok::comma))
+ Contexts.back().CanBeExpression = true;
+
FormatToken *Tok = CurrentToken;
if (!consumeToken())
return false;
@@ -235,10 +255,12 @@ private:
// A '[' could be an index subscript (after an identifier or after
// ')' or ']'), it could be the start of an Objective-C method
- // expression, or it could the the start of an Objective-C array literal.
+ // expression, or it could the start of an Objective-C array literal.
FormatToken *Left = CurrentToken->Previous;
+ Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
bool StartsObjCMethodExpr =
+ Style.Language == FormatStyle::LK_Cpp &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
CurrentToken->isNot(tok::l_brace) &&
(!Parent ||
@@ -247,19 +269,31 @@ private:
Parent->isUnaryOperator() ||
Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
- ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
- Contexts.back().IsExpression = true;
bool ColonFound = false;
- if (StartsObjCMethodExpr) {
- Contexts.back().ColonIsObjCMethodExpr = true;
- Left->Type = TT_ObjCMethodExpr;
- } else if (Parent && Parent->is(tok::at)) {
- Left->Type = TT_ArrayInitializerLSquare;
- } else if (Left->is(TT_Unknown)) {
- Left->Type = TT_ArraySubscriptLSquare;
+ unsigned BindingIncrease = 1;
+ if (Left->is(TT_Unknown)) {
+ if (StartsObjCMethodExpr) {
+ Left->Type = TT_ObjCMethodExpr;
+ } else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
+ Contexts.back().ContextKind == tok::l_brace &&
+ Parent->isOneOf(tok::l_brace, tok::comma)) {
+ Left->Type = TT_JsComputedPropertyName;
+ } else if (Parent &&
+ Parent->isOneOf(tok::at, tok::equal, tok::comma, tok::l_paren,
+ tok::l_square, tok::question, tok::colon,
+ tok::kw_return)) {
+ Left->Type = TT_ArrayInitializerLSquare;
+ } else {
+ BindingIncrease = 10;
+ Left->Type = TT_ArraySubscriptLSquare;
+ }
}
+ ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);
+ Contexts.back().IsExpression = true;
+ Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
+
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
@@ -300,10 +334,8 @@ private:
}
ColonFound = true;
}
- if (CurrentToken->is(tok::comma) &&
- Style.Language != FormatStyle::LK_Proto &&
- (Left->is(TT_ArraySubscriptLSquare) ||
- (Left->is(TT_ObjCMethodExpr) && !ColonFound)))
+ if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) &&
+ !ColonFound)
Left->Type = TT_ArrayInitializerLSquare;
FormatToken *Tok = CurrentToken;
if (!consumeToken())
@@ -316,6 +348,7 @@ private:
bool parseBrace() {
if (CurrentToken) {
FormatToken *Left = CurrentToken->Previous;
+ Left->ParentBracket = Contexts.back().ContextKind;
if (Contexts.back().CaretFound)
Left->Type = TT_ObjCBlockLBrace;
@@ -342,7 +375,8 @@ private:
Style.Language == FormatStyle::LK_Proto) &&
Previous->is(tok::identifier))
Previous->Type = TT_SelectorName;
- if (CurrentToken->is(tok::colon))
+ if (CurrentToken->is(tok::colon) ||
+ Style.Language == FormatStyle::LK_JavaScript)
Left->Type = TT_DictLiteral;
}
if (!consumeToken())
@@ -408,13 +442,22 @@ private:
if (!Tok->Previous)
return false;
// Colons from ?: are handled in parseConditional().
- if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1 &&
- Line.First->isNot(tok::kw_case)) {
- Tok->Type = TT_CtorInitializerColon;
- } else if (Contexts.back().ColonIsDictLiteral) {
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Contexts.back().ColonIsForRangeExpr || // colon in for loop
+ (Contexts.size() == 1 && // switch/case labels
+ !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
+ Contexts.back().ContextKind == tok::l_paren || // function params
+ Contexts.back().ContextKind == tok::l_square || // array type
+ (Contexts.size() == 1 &&
+ Line.MustBeDeclaration)) { // method/property declaration
+ Tok->Type = TT_JsTypeColon;
+ break;
+ }
+ }
+ if (Contexts.back().ColonIsDictLiteral) {
Tok->Type = TT_DictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
- Line.First->is(TT_ObjCMethodSpecifier)) {
+ Line.startsWith(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
Tok->Previous->Type = TT_SelectorName;
if (Tok->Previous->ColumnWidth >
@@ -429,7 +472,10 @@ private:
Tok->Type = TT_BitFieldColon;
} else if (Contexts.size() == 1 &&
!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
- Tok->Type = TT_InheritanceColon;
+ if (Tok->Previous->is(tok::r_paren))
+ Tok->Type = TT_CtorInitializerColon;
+ else
+ Tok->Type = TT_InheritanceColon;
} else if (Tok->Previous->is(tok::identifier) && Tok->Next &&
Tok->Next->isOneOf(tok::r_paren, tok::comma)) {
// This handles a special macro in ObjC code where selectors including
@@ -457,9 +503,10 @@ private:
if (!parseParens())
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
- !Contexts.back().IsExpression && Line.First->isNot(TT_ObjCProperty) &&
+ !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:
@@ -471,13 +518,15 @@ private:
return false;
break;
case tok::less:
- if ((!Tok->Previous ||
+ if (!NonTemplateLess.count(Tok) &&
+ (!Tok->Previous ||
(!Tok->Previous->Tok.isLiteral() &&
!(Tok->Previous->is(tok::r_paren) && Contexts.size() > 1))) &&
parseAngle()) {
Tok->Type = TT_TemplateOpener;
} else {
Tok->Type = TT_BinaryOperator;
+ NonTemplateLess.insert(Tok);
CurrentToken = Tok;
next();
}
@@ -509,21 +558,34 @@ private:
}
break;
case tok::question:
+ if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next &&
+ Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
+ tok::r_brace)) {
+ // Question marks before semicolons, colons, etc. indicate optional
+ // types (fields, parameters), e.g.
+ // function(x?: string, y?) {...}
+ // class X { y?; }
+ Tok->Type = TT_JsTypeOptionalQuestion;
+ break;
+ }
+ // Declarations cannot be conditional expressions, this can only be part
+ // of a type declaration.
+ if (Line.MustBeDeclaration &&
+ Style.Language == FormatStyle::LK_JavaScript)
+ break;
parseConditional();
break;
case tok::kw_template:
parseTemplateDeclaration();
break;
- case tok::identifier:
- if (Line.First->is(tok::kw_for) && Tok->is(Keywords.kw_in) &&
- Tok->Previous->isNot(tok::colon))
- Tok->Type = TT_ObjCForIn;
- break;
case tok::comma:
- if (Contexts.back().FirstStartOfName)
- Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
if (Contexts.back().InCtorInitializer)
Tok->Type = TT_CtorInitializerComma;
+ else if (Contexts.back().FirstStartOfName &&
+ (Contexts.size() == 1 || Line.startsWith(tok::kw_for))) {
+ Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
+ Line.IsMultiVariableDeclStmt = true;
+ }
if (Contexts.back().IsForEachMacro)
Contexts.back().IsExpression = true;
break;
@@ -557,11 +619,14 @@ private:
void parsePragma() {
next(); // Consume "pragma".
- if (CurrentToken && CurrentToken->TokenText == "mark") {
+ if (CurrentToken &&
+ CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option)) {
+ bool IsMark = CurrentToken->is(Keywords.kw_mark);
next(); // Consume "mark".
next(); // Consume first token (so we fix leading whitespace).
while (CurrentToken) {
- CurrentToken->Type = TT_ImplicitStringLiteral;
+ if (IsMark || CurrentToken->Previous->is(TT_BinaryOperator))
+ CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
}
@@ -582,6 +647,7 @@ private:
return Type;
switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
+ case tok::pp_include_next:
case tok::pp_import:
next();
parseIncludeDirective();
@@ -609,9 +675,9 @@ private:
public:
LineType parseLine() {
- if (CurrentToken->is(tok::hash)) {
+ NonTemplateLess.clear();
+ if (CurrentToken->is(tok::hash))
return parsePreprocessorDirective();
- }
// Directly allow to 'import <string-literal>' to support protocol buffer
// definitions (code.google.com/p/protobuf) or missing "#" (either way we
@@ -635,6 +701,15 @@ public:
return LT_ImportStatement;
}
+ // In .proto files, top-level options are very similar to import statements
+ // and should not be line-wrapped.
+ if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 &&
+ CurrentToken->is(Keywords.kw_option)) {
+ next();
+ if (CurrentToken && CurrentToken->is(tok::identifier))
+ return LT_ImportStatement;
+ }
+
bool KeywordVirtualFound = false;
bool ImportStatement = false;
while (CurrentToken) {
@@ -650,7 +725,7 @@ public:
if (ImportStatement)
return LT_ImportStatement;
- if (Line.First->is(TT_ObjCMethodSpecifier)) {
+ if (Line.startsWith(TT_ObjCMethodSpecifier)) {
if (Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
@@ -678,11 +753,13 @@ private:
// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
- if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_FunctionLBrace,
- TT_ImplicitStringLiteral, TT_RegexLiteral,
- TT_TrailingReturnArrow))
+ if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
+ TT_FunctionLBrace, TT_ImplicitStringLiteral,
+ TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
+ TT_RegexLiteral))
CurrentToken->Type = TT_Unknown;
CurrentToken->Role.reset();
+ CurrentToken->MatchingParen = nullptr;
CurrentToken->FakeLParens.clear();
CurrentToken->FakeRParens = 0;
}
@@ -705,27 +782,22 @@ private:
Context(tok::TokenKind ContextKind, unsigned BindingStrength,
bool IsExpression)
: ContextKind(ContextKind), BindingStrength(BindingStrength),
- LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
- ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
- FirstObjCSelectorName(nullptr), FirstStartOfName(nullptr),
- IsExpression(IsExpression), CanBeExpression(true),
- InTemplateArgument(false), InCtorInitializer(false),
- CaretFound(false), IsForEachMacro(false) {}
+ IsExpression(IsExpression) {}
tok::TokenKind ContextKind;
unsigned BindingStrength;
- unsigned LongestObjCSelectorName;
- bool ColonIsForRangeExpr;
- bool ColonIsDictLiteral;
- bool ColonIsObjCMethodExpr;
- FormatToken *FirstObjCSelectorName;
- FormatToken *FirstStartOfName;
bool IsExpression;
- bool CanBeExpression;
- bool InTemplateArgument;
- bool InCtorInitializer;
- bool CaretFound;
- bool IsForEachMacro;
+ unsigned LongestObjCSelectorName = 0;
+ bool ColonIsForRangeExpr = false;
+ bool ColonIsDictLiteral = false;
+ bool ColonIsObjCMethodExpr = false;
+ FormatToken *FirstObjCSelectorName = nullptr;
+ FormatToken *FirstStartOfName = nullptr;
+ bool CanBeExpression = true;
+ bool InTemplateArgument = false;
+ bool InCtorInitializer = false;
+ bool CaretFound = false;
+ bool IsForEachMacro = false;
};
/// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
@@ -746,27 +818,35 @@ private:
void modifyContext(const FormatToken &Current) {
if (Current.getPrecedence() == prec::Assignment &&
- !Line.First->isOneOf(tok::kw_template, tok::kw_using,
- TT_UnaryOperator) &&
+ !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
(!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
Contexts.back().IsExpression = true;
- for (FormatToken *Previous = Current.Previous;
- Previous && !Previous->isOneOf(tok::comma, tok::semi);
- Previous = Previous->Previous) {
- if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
- Previous = Previous->MatchingParen;
- if (!Previous)
+ if (!Line.startsWith(TT_UnaryOperator)) {
+ for (FormatToken *Previous = Current.Previous;
+ Previous && !Previous->isOneOf(tok::comma, tok::semi);
+ Previous = Previous->Previous) {
+ if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
+ Previous = Previous->MatchingParen;
+ if (!Previous)
+ break;
+ }
+ if (Previous->opensScope())
break;
+ if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
+ Previous->isOneOf(tok::star, tok::amp, tok::ampamp) &&
+ Previous->Previous && Previous->Previous->isNot(tok::equal))
+ Previous->Type = TT_PointerOrReference;
}
- if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
- Previous->isOneOf(tok::star, tok::amp) && Previous->Previous &&
- Previous->Previous->isNot(tok::equal))
- Previous->Type = TT_PointerOrReference;
}
+ } else if (Current.is(tok::lessless) &&
+ (!Current.Previous || !Current.Previous->is(tok::kw_operator))) {
+ Contexts.back().IsExpression = true;
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {
Contexts.back().IsExpression = true;
} else if (Current.is(TT_TrailingReturnArrow)) {
Contexts.back().IsExpression = false;
+ } else if (Current.is(TT_LambdaArrow)) {
+ Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java;
} else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
!Line.InPPDirective &&
(!Current.Previous ||
@@ -791,7 +871,7 @@ private:
Contexts.back().InCtorInitializer = true;
} else if (Current.is(tok::kw_new)) {
Contexts.back().CanBeExpression = false;
- } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
+ } else if (Current.isOneOf(tok::semi, tok::exclaim)) {
// This should be the condition or increment in a for-loop.
Contexts.back().IsExpression = true;
}
@@ -833,30 +913,56 @@ private:
} else if (Current.isOneOf(tok::exclaim, tok::tilde)) {
Current.Type = TT_UnaryOperator;
} else if (Current.is(tok::question)) {
- Current.Type = TT_ConditionalExpr;
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ Line.MustBeDeclaration) {
+ // In JavaScript, `interface X { foo?(): bar; }` is an optional method
+ // on the interface, not a ternary expression.
+ Current.Type = TT_JsTypeOptionalQuestion;
+ } else {
+ Current.Type = TT_ConditionalExpr;
+ }
} else if (Current.isBinaryOperator() &&
(!Current.Previous || Current.Previous->isNot(tok::l_square))) {
Current.Type = TT_BinaryOperator;
} else if (Current.is(tok::comment)) {
- if (Current.TokenText.startswith("//"))
+ if (Current.TokenText.startswith("/*")) {
+ if (Current.TokenText.endswith("*/"))
+ Current.Type = TT_BlockComment;
+ else
+ // The lexer has for some reason determined a comment here. But we
+ // cannot really handle it, if it isn't properly terminated.
+ Current.Tok.setKind(tok::unknown);
+ } else {
Current.Type = TT_LineComment;
- else
- Current.Type = TT_BlockComment;
+ }
} else if (Current.is(tok::r_paren)) {
if (rParenEndsCast(Current))
Current.Type = TT_CastRParen;
+ if (Current.MatchingParen && Current.Next &&
+ !Current.Next->isBinaryOperator() &&
+ !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace))
+ if (FormatToken *BeforeParen = Current.MatchingParen->Previous)
+ if (BeforeParen->is(tok::identifier) &&
+ BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
+ (!BeforeParen->Previous ||
+ BeforeParen->Previous->ClosesTemplateDeclaration))
+ Current.Type = TT_FunctionAnnotationRParen;
} else if (Current.is(tok::at) && Current.Next) {
- switch (Current.Next->Tok.getObjCKeywordID()) {
- case tok::objc_interface:
- case tok::objc_implementation:
- case tok::objc_protocol:
- Current.Type = TT_ObjCDecl;
- break;
- case tok::objc_property:
- Current.Type = TT_ObjCProperty;
- break;
- default:
- break;
+ if (Current.Next->isStringLiteral()) {
+ Current.Type = TT_ObjCStringLiteral;
+ } else {
+ switch (Current.Next->Tok.getObjCKeywordID()) {
+ case tok::objc_interface:
+ case tok::objc_implementation:
+ case tok::objc_protocol:
+ Current.Type = TT_ObjCDecl;
+ break;
+ case tok::objc_property:
+ Current.Type = TT_ObjCProperty;
+ break;
+ default:
+ break;
+ }
}
} else if (Current.is(tok::period)) {
FormatToken *PreviousNoComment = Current.getPreviousNonComment();
@@ -875,7 +981,9 @@ private:
// Line.MightBeFunctionDecl can only be true after the parentheses of a
// function declaration have been found.
Current.Type = TT_TrailingAnnotation;
- } else if (Style.Language == FormatStyle::LK_Java && Current.Previous) {
+ } else if ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ Current.Previous) {
if (Current.Previous->is(tok::at) &&
Current.isNot(Keywords.kw_interface)) {
const FormatToken &AtToken = *Current.Previous;
@@ -901,8 +1009,8 @@ private:
if (Tok.isNot(tok::identifier) || !Tok.Previous)
return false;
- if (Tok.Previous->is(TT_LeadingJavaAnnotation))
- return false;
+ if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof))
+ return false;
// Skip "const" as it does not have an influence on whether this is a name.
FormatToken *PreviousNotConst = Tok.Previous;
@@ -964,8 +1072,7 @@ private:
bool IsSizeOfOrAlignOf =
LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
- ((Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression) ||
- (Tok.Next && Tok.Next->isBinaryOperator())))
+ (Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression))
IsCast = true;
else if (Tok.Next && Tok.Next->isNot(tok::string_literal) &&
(Tok.Next->Tok.isLiteral() ||
@@ -975,7 +1082,7 @@ private:
// there is also an identifier before the ().
else if (LeftOfParens && Tok.Next &&
(LeftOfParens->Tok.getIdentifierInfo() == nullptr ||
- LeftOfParens->is(tok::kw_return)) &&
+ LeftOfParens->isOneOf(tok::kw_return, tok::kw_case)) &&
!LeftOfParens->isOneOf(TT_OverloadedOperator, tok::at,
TT_TemplateCloser)) {
if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
@@ -995,7 +1102,8 @@ private:
}
for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) {
- if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) {
+ if (!Prev ||
+ !Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon)) {
IsCast = false;
break;
}
@@ -1016,7 +1124,7 @@ private:
return TT_UnaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
- if (!NextToken ||
+ if (!NextToken || NextToken->is(tok::arrow) ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_Unknown;
@@ -1032,7 +1140,7 @@ private:
if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))
return TT_PointerOrReference;
- if (NextToken->isOneOf(tok::kw_operator, tok::comma))
+ if (NextToken->isOneOf(tok::kw_operator, tok::comma, tok::semi))
return TT_PointerOrReference;
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
@@ -1108,10 +1216,16 @@ private:
FormatToken *CurrentToken;
bool AutoFound;
const AdditionalKeywords &Keywords;
+
+ // Set of "<" tokens that do not open a template parameter list. If parseAngle
+ // determines that a specific token can't be a template opener, it will make
+ // same decision irrespective of the decisions for tokens leading up to it.
+ // Store this information to prevent this from causing exponential runtime.
+ llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;
};
-static int PrecedenceUnaryOperator = prec::PointerToMember + 1;
-static int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
+static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
+static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
/// \brief Parses binary expressions by inserting fake parenthesis based on
/// operator precedence.
@@ -1209,25 +1323,31 @@ private:
const FormatToken *NextNonComment = Current->getNextNonComment();
if (Current->is(TT_ConditionalExpr))
return prec::Conditional;
- else if (NextNonComment && NextNonComment->is(tok::colon) &&
- NextNonComment->is(TT_DictLiteral))
+ if (NextNonComment && NextNonComment->is(tok::colon) &&
+ NextNonComment->is(TT_DictLiteral))
return prec::Comma;
- else if (Current->is(TT_LambdaArrow))
+ if (Current->is(TT_LambdaArrow))
return prec::Comma;
- else if (Current->isOneOf(tok::semi, TT_InlineASMColon,
- TT_SelectorName) ||
- (Current->is(tok::comment) && NextNonComment &&
- NextNonComment->is(TT_SelectorName)))
+ if (Current->is(TT_JsFatArrow))
+ return prec::Assignment;
+ if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName,
+ TT_JsComputedPropertyName) ||
+ (Current->is(tok::comment) && NextNonComment &&
+ NextNonComment->is(TT_SelectorName)))
return 0;
- else if (Current->is(TT_RangeBasedForLoopColon))
+ if (Current->is(TT_RangeBasedForLoopColon))
return prec::Comma;
- else if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
+ if ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ Current->is(Keywords.kw_instanceof))
+ return prec::Relational;
+ if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
return Current->getPrecedence();
- else if (Current->isOneOf(tok::period, tok::arrow))
+ if (Current->isOneOf(tok::period, tok::arrow))
return PrecedenceArrowAndPeriod;
- else if (Style.Language == FormatStyle::LK_Java &&
- Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
- Keywords.kw_throws))
+ if (Style.Language == FormatStyle::LK_Java &&
+ Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
+ Keywords.kw_throws))
return 0;
}
return -1;
@@ -1326,11 +1446,11 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
ExpressionParser ExprParser(Style, Keywords, Line);
ExprParser.parse();
- if (Line.First->is(TT_ObjCMethodSpecifier))
+ if (Line.startsWith(TT_ObjCMethodSpecifier))
Line.Type = LT_ObjCMethodDecl;
- else if (Line.First->is(TT_ObjCDecl))
+ else if (Line.startsWith(TT_ObjCDecl))
Line.Type = LT_ObjCDecl;
- else if (Line.First->is(TT_ObjCProperty))
+ else if (Line.startsWith(TT_ObjCProperty))
Line.Type = LT_ObjCProperty;
Line.First->SpacesRequiredBefore = 1;
@@ -1361,12 +1481,13 @@ static bool isFunctionDeclarationName(const FormatToken &Current) {
assert(Next->is(tok::l_paren));
if (Next->Next == Next->MatchingParen)
return true;
- for (const FormatToken *Tok = Next->Next; Tok != Next->MatchingParen;
+ for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
Tok = Tok->Next) {
if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
Tok->isOneOf(TT_PointerOrReference, TT_StartOfName))
return true;
- if (Tok->isOneOf(tok::l_brace, tok::string_literal) || Tok->Tok.isLiteral())
+ if (Tok->isOneOf(tok::l_brace, tok::string_literal, TT_ObjCMethodExpr) ||
+ Tok->Tok.isLiteral())
return false;
}
return false;
@@ -1423,8 +1544,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
Current->MustBreakBefore =
Current->MustBreakBefore || mustBreakBefore(Line, *Current);
- if (Style.AlwaysBreakAfterDefinitionReturnType && InFunctionDecl &&
- Current->is(TT_FunctionDeclarationName) &&
+ if ((Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All ||
+ (Style.AlwaysBreakAfterDefinitionReturnType ==
+ FormatStyle::DRTBS_TopLevel &&
+ Line.Level == 0)) &&
+ InFunctionDecl && Current->is(TT_FunctionDeclarationName) &&
!Line.Last->isOneOf(tok::semi, tok::comment)) // Only for definitions.
// FIXME: Line.Last points to other characters than tok::semi
// and tok::lbrace.
@@ -1502,7 +1626,9 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::comma) && Left.NestingLevel == 0)
return 3;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Right.is(Keywords.kw_function))
+ if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
+ return 100;
+ if (Left.is(TT_JsTypeColon))
return 100;
}
@@ -1512,20 +1638,28 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
return 1;
- if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare))
+ // Slightly prefer formatting local lambda definitions like functions.
+ if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))
+ return 50;
+ if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
+ TT_ArrayInitializerLSquare))
return 500;
}
if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
Right.is(tok::kw_operator)) {
- if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
+ if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
if (Left.is(TT_StartOfName))
- return 20;
+ return 110;
if (InFunctionDecl && Right.NestingLevel == 0)
return Style.PenaltyReturnTypeOnItsOwnLine;
return 200;
}
+ if (Right.is(TT_PointerOrReference))
+ return 190;
+ if (Right.is(TT_LambdaArrow))
+ return 110;
if (Left.is(tok::equal) && Right.is(tok::l_brace))
return 150;
if (Left.is(TT_CastRParen))
@@ -1550,8 +1684,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
(!Right.Next || Right.Next->isNot(tok::l_paren))) {
// Moving trailing annotations to the next line is fine for ObjC method
// declarations.
- if (Line.First->is(TT_ObjCMethodSpecifier))
-
+ if (Line.startsWith(TT_ObjCMethodSpecifier))
return 10;
// Generally, breaking before a trailing annotation is bad unless it is
// function-like. It seems to be especially preferable to keep standard
@@ -1563,7 +1696,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
}
// In for-loops, prefer breaking at ',' and ';'.
- if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
+ if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))
return 4;
// In Objective-C method expressions, prefer breaking before "param:" over
@@ -1575,6 +1708,9 @@ 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->isOneOf(tok::kw_if, tok::kw_for))
+ return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
if (Right.is(tok::r_brace))
@@ -1591,7 +1727,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 50;
if (Right.is(tok::lessless)) {
- if (Left.is(tok::string_literal)) {
+ if (Left.is(tok::string_literal) &&
+ (!Right.LastOperator || Right.OperatorIndex != 1)) {
StringRef Content = Left.TokenText;
if (Content.startswith("\""))
Content = Content.drop_front(1);
@@ -1607,7 +1744,9 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_ConditionalExpr))
return prec::Conditional;
prec::Level Level = Left.getPrecedence();
-
+ if (Level != prec::Unknown)
+ return Level;
+ Level = Right.getPrecedence();
if (Level != prec::Unknown)
return Level;
@@ -1636,7 +1775,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.isOneOf(tok::semi, tok::comma))
return false;
if (Right.is(tok::less) &&
- (Left.isOneOf(tok::kw_template, tok::r_paren) ||
+ (Left.is(tok::kw_template) ||
(Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
return true;
if (Left.isOneOf(tok::exclaim, tok::tilde))
@@ -1655,17 +1794,28 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::l_square) && Right.is(tok::amp))
return false;
if (Right.is(TT_PointerOrReference))
- return Left.Tok.isLiteral() ||
- (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
- Style.PointerAlignment != FormatStyle::PAS_Left);
+ return !(Left.is(tok::r_paren) && Left.MatchingParen &&
+ (Left.MatchingParen->is(TT_OverloadedOperatorLParen) ||
+ (Left.MatchingParen->Previous &&
+ Left.MatchingParen->Previous->is(
+ TT_FunctionDeclarationName)))) &&
+ (Left.Tok.isLiteral() ||
+ (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
+ (Style.PointerAlignment != FormatStyle::PAS_Left ||
+ Line.IsMultiVariableDeclStmt)));
if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
(!Left.is(TT_PointerOrReference) ||
- Style.PointerAlignment != FormatStyle::PAS_Right))
+ (Style.PointerAlignment != FormatStyle::PAS_Right &&
+ !Line.IsMultiVariableDeclStmt)))
return true;
if (Left.is(TT_PointerOrReference))
return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
- (!Right.isOneOf(TT_PointerOrReference, tok::l_paren) &&
- Style.PointerAlignment != FormatStyle::PAS_Right && Left.Previous &&
+ (Right.is(tok::l_brace) && Right.BlockKind == BK_Block) ||
+ (!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
+ tok::l_paren) &&
+ (Style.PointerAlignment != FormatStyle::PAS_Right &&
+ !Line.IsMultiVariableDeclStmt) &&
+ Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
@@ -1700,13 +1850,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while,
- tok::kw_switch, tok::kw_case) ||
- (Left.isOneOf(tok::kw_try, tok::kw_catch, tok::kw_new,
- tok::kw_delete) &&
- (!Left.Previous || Left.Previous->isNot(tok::period))) ||
- Left.IsForEachMacro)) ||
+ tok::kw_switch, tok::kw_case, TT_ForEachMacro) ||
+ (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
+ tok::kw_new, tok::kw_delete) &&
+ (!Left.Previous || Left.Previous->isNot(tok::period))))) ||
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
- (Left.is(tok::identifier) || Left.isFunctionLikeKeyword()) &&
+ (Left.is(tok::identifier) || Left.isFunctionLikeKeyword() ||
+ Left.is(tok::r_paren)) &&
Line.Type != LT_PreprocessorDirective);
}
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
@@ -1737,7 +1887,12 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
- if (Style.Language == FormatStyle::LK_Proto) {
+ if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
+ return true; // Never ever merge two identifiers.
+ if (Style.Language == FormatStyle::LK_Cpp) {
+ if (Left.is(tok::kw_operator))
+ return Right.is(tok::coloncolon);
+ } else if (Style.Language == FormatStyle::LK_Proto) {
if (Right.is(tok::period) &&
Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
Keywords.kw_repeated))
@@ -1746,13 +1901,25 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Left.is(Keywords.kw_var))
+ if (Left.isOneOf(Keywords.kw_var, TT_JsFatArrow))
return true;
+ if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))
+ return false;
+ if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&
+ Line.First->isOneOf(Keywords.kw_import, tok::kw_export))
+ return false;
+ if (Left.is(tok::ellipsis))
+ return false;
+ if (Left.is(TT_TemplateCloser) &&
+ !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,
+ Keywords.kw_implements, Keywords.kw_extends))
+ // Type assertions ('<type>expr') are not followed by whitespace. Other
+ // locations that should have whitespace following are identified by the
+ // above set of follower tokens.
+ return false;
} else if (Style.Language == FormatStyle::LK_Java) {
if (Left.is(tok::r_square) && Right.is(tok::l_brace))
return true;
- if (Left.is(TT_LambdaArrow) || Right.is(TT_LambdaArrow))
- return true;
if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren))
return Style.SpaceBeforeParens != FormatStyle::SBPO_Never;
if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
@@ -1762,8 +1929,6 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Right.is(TT_TemplateOpener))
return true;
}
- if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
- return true; // Never ever merge two identifiers.
if (Left.is(TT_ImplicitStringLiteral))
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
if (Line.Type == LT_ObjCMethodDecl) {
@@ -1777,7 +1942,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
(Right.is(tok::equal) || Left.is(tok::equal)))
return false;
- if (Right.is(TT_TrailingReturnArrow) || Left.is(TT_TrailingReturnArrow))
+ if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
+ Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
return true;
if (Left.is(tok::comma))
return true;
@@ -1785,24 +1951,34 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
return true;
- if (Left.is(tok::kw_operator))
- return Right.is(tok::coloncolon);
if (Right.is(TT_OverloadedOperatorLParen))
return false;
- if (Right.is(tok::colon))
- return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
- Right.getNextNonComment() && Right.isNot(TT_ObjCMethodExpr) &&
- !Left.is(tok::question) &&
- !(Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon)) &&
- (Right.isNot(TT_DictLiteral) || Style.SpacesInContainerLiterals);
+ if (Right.is(tok::colon)) {
+ if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
+ !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
+ return false;
+ if (Right.is(TT_ObjCMethodExpr))
+ return false;
+ if (Left.is(tok::question))
+ return false;
+ if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))
+ return false;
+ if (Right.is(TT_DictLiteral))
+ return Style.SpacesInContainerLiterals;
+ return true;
+ }
if (Left.is(TT_UnaryOperator))
return Right.is(TT_BinaryOperator);
+
+ // If the next token is a binary operator or a selector name, we have
+ // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
if (Left.is(TT_CastRParen))
- return Style.SpaceAfterCStyleCast || Right.is(TT_BinaryOperator);
- if (Left.is(tok::greater) && Right.is(tok::greater)) {
+ return Style.SpaceAfterCStyleCast ||
+ Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
+
+ if (Left.is(tok::greater) && Right.is(tok::greater))
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
- }
if (Right.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar))
return false;
@@ -1819,13 +1995,14 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr))
return true;
- if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren))
+ if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren) &&
+ Right.isNot(TT_FunctionTypeLParen))
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
return false;
if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
- Line.First->is(tok::hash))
+ Line.startsWith(tok::hash))
return true;
if (Right.is(TT_TrailingUnaryOperator))
return false;
@@ -1846,13 +2023,49 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.NewlinesBefore > 1)
return true;
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ // FIXME: This might apply to other languages and token kinds.
+ if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
+ Left.Previous->is(tok::char_constant))
+ return true;
+ if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
+ Left.Previous && Left.Previous->is(tok::equal) &&
+ Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
+ tok::kw_const) &&
+ // kw_var is a pseudo-token that's a tok::identifier, so matches above.
+ !Line.startsWith(Keywords.kw_var))
+ // Object literals on the top level of a file are treated as "enum-style".
+ // Each key/value pair is put on a separate line, instead of bin-packing.
+ return true;
+ if (Left.is(tok::l_brace) && Line.Level == 0 &&
+ (Line.startsWith(tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_enum)))
+ // JavaScript top-level enum key/value pairs are put on separate lines
+ // instead of bin-packing.
+ return true;
+ if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
+ !Left.Children.empty())
+ // Support AllowShortFunctionsOnASingleLine for JavaScript.
+ return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
+ (Left.NestingLevel == 0 && Line.Level == 0 &&
+ Style.AllowShortFunctionsOnASingleLine ==
+ FormatStyle::SFS_Inline);
+ } else if (Style.Language == FormatStyle::LK_Java) {
+ if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
+ Right.Next->is(tok::string_literal))
+ return true;
+ }
+
// If the last token before a '}' is a comma or a trailing comment, the
// intention is to insert a line break after it in order to make shuffling
// around entries easier.
const FormatToken *BeforeClosingBrace = nullptr;
- if (Left.is(tok::l_brace) && Left.BlockKind != BK_Block && Left.MatchingParen)
+ if (Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
+ Left.BlockKind != BK_Block && Left.MatchingParen)
BeforeClosingBrace = Left.MatchingParen->Previous;
- else if (Right.is(tok::r_brace) && Right.BlockKind != BK_Block)
+ else if (Right.MatchingParen &&
+ Right.MatchingParen->isOneOf(tok::l_brace,
+ TT_ArrayInitializerLSquare))
BeforeClosingBrace = &Left;
if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
BeforeClosingBrace->isTrailingComment()))
@@ -1862,8 +2075,10 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return Left.BlockKind != BK_BracedInit &&
Left.isNot(TT_CtorInitializerColon) &&
(Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
- if (Right.Previous->isTrailingComment() ||
- (Right.isStringLiteral() && Right.Previous->isStringLiteral()))
+ if (Left.isTrailingComment())
+ return true;
+ if (Left.isStringLiteral() &&
+ (Right.isStringLiteral() || Right.is(TT_ObjCStringLiteral)))
return true;
if (Right.Previous->IsUnterminatedLiteral)
return true;
@@ -1889,41 +2104,25 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Style.Language == FormatStyle::LK_Proto)
// Don't put enums onto single lines in protocol buffers.
return true;
- if (Style.Language == FormatStyle::LK_JavaScript && Right.is(tok::r_brace) &&
- Left.is(tok::l_brace) && !Left.Children.empty())
- // Support AllowShortFunctionsOnASingleLine for JavaScript.
- return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
- (Left.NestingLevel == 0 && Line.Level == 0 &&
- Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline);
+ if (Right.is(TT_InlineASMBrace))
+ 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;
if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
return true;
- if (Right.is(tok::lessless) && Left.is(tok::identifier) &&
- Left.TokenText == "endl")
- return true;
- if (Style.Language == FormatStyle::LK_JavaScript) {
- // FIXME: This might apply to other languages and token kinds.
- if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
- Left.Previous->is(tok::char_constant))
- return true;
- if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) &&
- Left.NestingLevel == 0)
- return true;
- } else if (Style.Language == FormatStyle::LK_Java) {
- if (Left.is(TT_LeadingJavaAnnotation) &&
- Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
- Line.Last->is(tok::l_brace))
- return true;
- if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
- Right.Next->is(tok::string_literal))
- return true;
- }
+ if ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ Left.is(TT_LeadingJavaAnnotation) &&
+ Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
+ Line.Last->is(tok::l_brace))
+ return true;
return false;
}
@@ -1932,6 +2131,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
+ // Language-specific stuff.
if (Style.Language == FormatStyle::LK_Java) {
if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
Keywords.kw_implements))
@@ -1939,6 +2139,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
Keywords.kw_implements))
return true;
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
+ return false;
+ if (Left.is(TT_JsTypeColon))
+ return true;
}
if (Left.is(tok::at))
@@ -1947,9 +2152,15 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return false;
if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))
return !Right.is(tok::l_paren);
+ if (Right.is(TT_PointerOrReference))
+ return Line.IsMultiVariableDeclStmt ||
+ (Style.PointerAlignment == FormatStyle::PAS_Right &&
+ (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));
if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
Right.is(tok::kw_operator))
return true;
+ if (Left.is(TT_PointerOrReference))
+ return false;
if (Right.isTrailingComment())
// We rely on MustBreakBefore being set correctly here as we should not
// change the "binding" behavior of a comment.
@@ -1970,8 +2181,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return false;
if (Left.is(tok::colon) && (Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))
return true;
- if (Right.is(TT_SelectorName))
- return true;
+ if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
+ Right.Next->is(TT_ObjCMethodExpr)))
+ return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
return true;
if (Left.ClosesTemplateDeclaration)
@@ -1983,23 +2195,25 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return true;
if (Right.is(TT_RangeBasedForLoopColon))
return false;
- if (Left.isOneOf(TT_PointerOrReference, TT_TemplateCloser,
- TT_UnaryOperator) ||
+ if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||
Left.is(tok::kw_operator))
return false;
- if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
+ if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
+ Line.Type == LT_VirtualFunctionDecl)
return false;
if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen))
return false;
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen) ||
- Left.Previous->is(tok::kw_if)))
+ (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen)))
return false;
if (Right.is(TT_ImplicitStringLiteral))
return false;
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.
@@ -2027,8 +2241,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
return true;
- if (Left.is(tok::greater) && Right.is(tok::greater) &&
- Left.isNot(TT_TemplateCloser))
+ if ((Left.is(tok::greater) && Right.is(tok::greater)) ||
+ (Left.is(tok::less) && Right.is(tok::less)))
return false;
if (Right.is(TT_BinaryOperator) &&
Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&
@@ -2039,15 +2253,17 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return true;
if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))
return true;
- if (Left.isBinaryOperator() && !Left.isOneOf(tok::arrowstar, tok::lessless) &&
+ if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) &&
+ !Left.isOneOf(tok::arrowstar, tok::lessless) &&
Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&
(Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
Left.getPrecedence() == prec::Assignment))
return true;
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct) ||
- Right.isMemberAccess() || Right.is(TT_TrailingReturnArrow) ||
- Right.isOneOf(tok::lessless, tok::colon, tok::l_square, tok::at) ||
+ Right.isMemberAccess() ||
+ Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
+ tok::colon, tok::l_square, tok::at) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||
(Left.is(tok::l_paren) && !Right.is(tok::r_paren));
@@ -2058,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/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
index ff8e32a..b8a6be0 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
@@ -42,8 +42,8 @@ public:
: First(Line.Tokens.front().Tok), Level(Line.Level),
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
- Affected(false), LeadingEmptyLinesAffected(false),
- ChildrenAffected(false) {
+ IsMultiVariableDeclStmt(false), Affected(false),
+ LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
assert(!Line.Tokens.empty());
// Calculate Next and Previous for all tokens. Note that we must overwrite
@@ -59,11 +59,8 @@ public:
I->Tok->Previous = Current;
Current = Current->Next;
Current->Children.clear();
- for (SmallVectorImpl<UnwrappedLine>::const_iterator
- I = Node.Children.begin(),
- E = Node.Children.end();
- I != E; ++I) {
- Children.push_back(new AnnotatedLine(*I));
+ for (const auto &Child : Node.Children) {
+ Children.push_back(new AnnotatedLine(Child));
Current->Children.push_back(Children.back());
}
}
@@ -75,6 +72,18 @@ public:
for (unsigned i = 0, e = Children.size(); i != e; ++i) {
delete Children[i];
}
+ FormatToken *Current = First;
+ while (Current) {
+ Current->Children.clear();
+ Current->Role.reset();
+ Current = Current->Next;
+ }
+ }
+
+ /// \c true if this line starts with the given tokens in order, ignoring
+ /// comments.
+ template <typename... Ts> bool startsWith(Ts... Tokens) const {
+ return startsWith(First, Tokens...);
}
FormatToken *First;
@@ -87,6 +96,7 @@ public:
bool InPPDirective;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
+ bool IsMultiVariableDeclStmt;
/// \c True if this line should be formatted, i.e. intersects directly or
/// indirectly with one of the input ranges.
@@ -101,8 +111,20 @@ public:
private:
// Disallow copying.
- AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
- void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
+ AnnotatedLine(const AnnotatedLine &) = delete;
+ void operator=(const AnnotatedLine &) = delete;
+
+ template <typename A, typename... Ts>
+ bool startsWith(FormatToken *Tok, A K1) const {
+ while (Tok && Tok->is(tok::comment))
+ Tok = Tok->Next;
+ return Tok && Tok->is(K1);
+ }
+
+ template <typename A, typename... Ts>
+ bool startsWith(FormatToken *Tok, A K1, Ts... Tokens) const {
+ return startsWith(Tok, K1) && startsWith(Tok->Next, Tokens...);
+ }
};
/// \brief Determines extra information about the tokens comprising an
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
index ca66e73..b6784b3 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -21,23 +21,158 @@ namespace {
bool startsExternCBlock(const AnnotatedLine &Line) {
const FormatToken *Next = Line.First->getNextNonComment();
const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;
- return Line.First->is(tok::kw_extern) && Next && Next->isStringLiteral() &&
+ return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() &&
NextNext && NextNext->is(tok::l_brace);
}
+/// \brief Tracks the indent level of \c AnnotatedLines across levels.
+///
+/// \c nextLine must be called for each \c AnnotatedLine, after which \c
+/// getIndent() will return the indent for the last line \c nextLine was called
+/// with.
+/// If the line is not formatted (and thus the indent does not change), calling
+/// \c adjustToUnmodifiedLine after the call to \c nextLine will cause
+/// subsequent lines on the same level to be indented at the same level as the
+/// given line.
+class LevelIndentTracker {
+public:
+ LevelIndentTracker(const FormatStyle &Style,
+ const AdditionalKeywords &Keywords, unsigned StartLevel,
+ int AdditionalIndent)
+ : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
+ for (unsigned i = 0; i != StartLevel; ++i)
+ IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
+ }
+
+ /// \brief Returns the indent for the current line.
+ unsigned getIndent() const { return Indent; }
+
+ /// \brief Update the indent state given that \p Line is going to be formatted
+ /// next.
+ void nextLine(const AnnotatedLine &Line) {
+ Offset = getIndentOffset(*Line.First);
+ // Update the indent level cache size so that we can rely on it
+ // having the right size in adjustToUnmodifiedline.
+ while (IndentForLevel.size() <= Line.Level)
+ IndentForLevel.push_back(-1);
+ if (Line.InPPDirective) {
+ Indent = Line.Level * Style.IndentWidth + AdditionalIndent;
+ } else {
+ IndentForLevel.resize(Line.Level + 1);
+ Indent = getIndent(IndentForLevel, Line.Level);
+ }
+ if (static_cast<int>(Indent) + Offset >= 0)
+ Indent += Offset;
+ }
+
+ /// \brief Update the level indent to adapt to the given \p Line.
+ ///
+ /// When a line is not formatted, we move the subsequent lines on the same
+ /// level to the same indent.
+ /// Note that \c nextLine must have been called before this method.
+ void adjustToUnmodifiedLine(const AnnotatedLine &Line) {
+ unsigned LevelIndent = Line.First->OriginalColumn;
+ if (static_cast<int>(LevelIndent) - Offset >= 0)
+ LevelIndent -= Offset;
+ if ((!Line.First->is(tok::comment) || IndentForLevel[Line.Level] == -1) &&
+ !Line.InPPDirective)
+ IndentForLevel[Line.Level] = LevelIndent;
+ }
+
+private:
+ /// \brief Get the offset of the line relatively to the level.
+ ///
+ /// For example, 'public:' labels in classes are offset by 1 or 2
+ /// characters to the left from their level.
+ int getIndentOffset(const FormatToken &RootToken) {
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript)
+ return 0;
+ if (RootToken.isAccessSpecifier(false) ||
+ RootToken.isObjCAccessSpecifier() ||
+ (RootToken.is(Keywords.kw_signals) && RootToken.Next &&
+ RootToken.Next->is(tok::colon)))
+ return Style.AccessModifierOffset;
+ return 0;
+ }
+
+ /// \brief Get the indent of \p Level from \p IndentForLevel.
+ ///
+ /// \p IndentForLevel must contain the indent for the level \c l
+ /// at \p IndentForLevel[l], or a value < 0 if the indent for
+ /// that level is unknown.
+ unsigned getIndent(ArrayRef<int> IndentForLevel, unsigned Level) {
+ if (IndentForLevel[Level] != -1)
+ return IndentForLevel[Level];
+ if (Level == 0)
+ return 0;
+ return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
+ }
+
+ const FormatStyle &Style;
+ const AdditionalKeywords &Keywords;
+ const unsigned AdditionalIndent;
+
+ /// \brief The indent in characters for each level.
+ std::vector<int> IndentForLevel;
+
+ /// \brief Offset of the current line relative to the indent level.
+ ///
+ /// For example, the 'public' keywords is often indented with a negative
+ /// offset.
+ int Offset = 0;
+
+ /// \brief The current line's indent.
+ unsigned Indent = 0;
+};
+
class LineJoiner {
public:
- LineJoiner(const FormatStyle &Style) : Style(Style) {}
+ LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords,
+ const SmallVectorImpl<AnnotatedLine *> &Lines)
+ : Style(Style), Keywords(Keywords), End(Lines.end()),
+ Next(Lines.begin()) {}
+
+ /// \brief Returns the next line, merging multiple lines into one if possible.
+ const AnnotatedLine *getNextMergedLine(bool DryRun,
+ LevelIndentTracker &IndentTracker) {
+ if (Next == End)
+ return nullptr;
+ const AnnotatedLine *Current = *Next;
+ IndentTracker.nextLine(*Current);
+ unsigned MergedLines =
+ tryFitMultipleLinesInOne(IndentTracker.getIndent(), Next, End);
+ if (MergedLines > 0 && Style.ColumnLimit == 0)
+ // Disallow line merging if there is a break at the start of one of the
+ // input lines.
+ for (unsigned i = 0; i < MergedLines; ++i)
+ if (Next[i + 1]->First->NewlinesBefore > 0)
+ MergedLines = 0;
+ if (!DryRun)
+ for (unsigned i = 0; i < MergedLines; ++i)
+ join(*Next[i], *Next[i + 1]);
+ Next = Next + MergedLines + 1;
+ return Current;
+ }
+private:
/// \brief Calculates how many lines can be merged into 1 starting at \p I.
unsigned
tryFitMultipleLinesInOne(unsigned Indent,
SmallVectorImpl<AnnotatedLine *>::const_iterator I,
SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
+ // Can't join the last line with anything.
+ if (I + 1 == E)
+ return 0;
// We can never merge stuff if there are trailing line comments.
const AnnotatedLine *TheLine = *I;
if (TheLine->Last->is(TT_LineComment))
return 0;
+ if (I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
+ return 0;
+ if (TheLine->InPPDirective &&
+ (!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline))
+ return 0;
if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
return 0;
@@ -50,14 +185,11 @@ public:
? 0
: Limit - TheLine->Last->TotalLength;
- if (I + 1 == E || I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
- return 0;
-
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
// If necessary, change to something smarter.
bool MergeShortFunctions =
Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
- (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty &&
+ (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
I[1]->First->is(tok::r_brace)) ||
(Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
TheLine->Level != 0);
@@ -113,15 +245,12 @@ public:
return 0;
}
-private:
unsigned
tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
unsigned Limit) {
if (Limit == 0)
return 0;
- if (!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline)
- return 0;
if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
return 0;
if (1 + I[1]->Last->TotalLength > Limit)
@@ -147,19 +276,20 @@ private:
return 0;
if (1 + I[1]->Last->TotalLength > Limit)
return 0;
- if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
- tok::kw_while, TT_LineComment))
+ if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
+ TT_LineComment))
return 0;
// Only inline simple if's (no nested if or else).
- if (I + 2 != E && Line.First->is(tok::kw_if) &&
+ if (I + 2 != E && Line.startsWith(tok::kw_if) &&
I[2]->First->is(tok::kw_else))
return 0;
return 1;
}
- unsigned tryMergeShortCaseLabels(
- SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
+ unsigned
+ tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
+ SmallVectorImpl<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (Limit == 0 || I + 1 == E ||
I[1]->First->isOneOf(tok::kw_case, tok::kw_default))
return 0;
@@ -191,27 +321,35 @@ private:
AnnotatedLine &Line = **I;
// Don't merge ObjC @ keywords and methods.
+ // FIXME: If an option to allow short exception handling clauses on a single
+ // line is added, change this to not return for @try and friends.
if (Style.Language != FormatStyle::LK_Java &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
return 0;
// Check that the current line allows merging. This depends on whether we
// are in a control flow statements as well as several style flags.
- if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
+ if (Line.First->isOneOf(tok::kw_else, tok::kw_case) ||
+ (Line.First->Next && Line.First->Next->is(tok::kw_else)))
return 0;
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
- tok::kw_catch, tok::kw_for, tok::r_brace)) {
+ tok::kw___try, tok::kw_catch, tok::kw___finally,
+ tok::kw_for, tok::r_brace, Keywords.kw___except)) {
if (!Style.AllowShortBlocksOnASingleLine)
return 0;
if (!Style.AllowShortIfStatementsOnASingleLine &&
- Line.First->is(tok::kw_if))
+ Line.startsWith(tok::kw_if))
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
return 0;
// FIXME: Consider an option to allow short exception handling clauses on
// a single line.
- if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
+ // FIXME: This isn't covered by tests.
+ // FIXME: For catch, __except, __finally the first token on the line
+ // is '}', so this isn't correct here.
+ if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
+ Keywords.kw___except, tok::kw___finally))
return 0;
}
@@ -223,10 +361,11 @@ private:
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
return 1;
- } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace) &&
+ } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
!startsExternCBlock(Line)) {
// We don't merge short records.
- if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
+ if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
+ Keywords.kw_interface))
return 0;
// Check that we still have three lines and they fit into the limit.
@@ -252,6 +391,10 @@ private:
if (Tok->isNot(tok::r_brace))
return 0;
+ // Don't merge "if (a) { .. } else {".
+ if (Tok->Next && Tok->Next->is(tok::kw_else))
+ return 0;
+
return 2;
}
return 0;
@@ -285,28 +428,367 @@ private:
return false;
}
+ void join(AnnotatedLine &A, const AnnotatedLine &B) {
+ assert(!A.Last->Next);
+ assert(!B.First->Previous);
+ if (B.Affected)
+ A.Affected = true;
+ A.Last->Next = B.First;
+ B.First->Previous = A.Last;
+ B.First->CanBreakBefore = true;
+ unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
+ for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
+ Tok->TotalLength += LengthA;
+ A.Last = Tok;
+ }
+ }
+
const FormatStyle &Style;
+ const AdditionalKeywords &Keywords;
+ const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
+
+ SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
};
-class NoColumnLimitFormatter {
+static void markFinalized(FormatToken *Tok) {
+ for (; Tok; Tok = Tok->Next) {
+ Tok->Finalized = true;
+ for (AnnotatedLine *Child : Tok->Children)
+ markFinalized(Child->First);
+ }
+}
+
+#ifndef NDEBUG
+static void printLineState(const LineState &State) {
+ llvm::dbgs() << "State: ";
+ for (const ParenState &P : State.Stack) {
+ llvm::dbgs() << P.Indent << "|" << P.LastSpace << "|" << P.NestedBlockIndent
+ << " ";
+ }
+ llvm::dbgs() << State.NextToken->TokenText << "\n";
+}
+#endif
+
+/// \brief Base class for classes that format one \c AnnotatedLine.
+class LineFormatter {
public:
- NoColumnLimitFormatter(ContinuationIndenter *Indenter) : Indenter(Indenter) {}
+ LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
+ const FormatStyle &Style,
+ UnwrappedLineFormatter *BlockFormatter)
+ : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
+ BlockFormatter(BlockFormatter) {}
+ virtual ~LineFormatter() {}
+
+ /// \brief Formats an \c AnnotatedLine and returns the penalty.
+ ///
+ /// If \p DryRun is \c false, directly applies the changes.
+ virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+ bool DryRun) = 0;
+
+protected:
+ /// \brief If the \p State's next token is an r_brace closing a nested block,
+ /// format the nested block before it.
+ ///
+ /// Returns \c true if all children could be placed successfully and adapts
+ /// \p Penalty as well as \p State. If \p DryRun is false, also directly
+ /// creates changes using \c Whitespaces.
+ ///
+ /// The crucial idea here is that children always get formatted upon
+ /// encountering the closing brace right after the nested block. Now, if we
+ /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
+ /// \c false), the entire block has to be kept on the same line (which is only
+ /// possible if it fits on the line, only contains a single statement, etc.
+ ///
+ /// If \p NewLine is true, we format the nested block on separate lines, i.e.
+ /// break after the "{", format all lines with correct indentation and the put
+ /// the closing "}" on yet another new line.
+ ///
+ /// This enables us to keep the simple structure of the
+ /// \c UnwrappedLineFormatter, where we only have two options for each token:
+ /// break or don't break.
+ bool formatChildren(LineState &State, bool NewLine, bool DryRun,
+ unsigned &Penalty) {
+ const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
+ FormatToken &Previous = *State.NextToken->Previous;
+ if (!LBrace || LBrace->isNot(tok::l_brace) ||
+ LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
+ // The previous token does not open a block. Nothing to do. We don't
+ // assert so that we can simply call this function for all tokens.
+ return true;
+
+ if (NewLine) {
+ int AdditionalIndent = State.Stack.back().Indent -
+ Previous.Children[0]->Level * Style.IndentWidth;
+
+ Penalty +=
+ BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,
+ /*FixBadIndentation=*/true);
+ return true;
+ }
+
+ if (Previous.Children[0]->First->MustBreakBefore)
+ return false;
+
+ // Cannot merge multiple statements into a single line.
+ if (Previous.Children.size() > 1)
+ return false;
+
+ // Cannot merge into one line if this line ends on a comment.
+ if (Previous.is(tok::comment))
+ return false;
+
+ // We can't put the closing "}" on a line with a trailing comment.
+ if (Previous.Children[0]->Last->isTrailingComment())
+ return false;
+
+ // If the child line exceeds the column limit, we wouldn't want to merge it.
+ // We add +2 for the trailing " }".
+ if (Style.ColumnLimit > 0 &&
+ Previous.Children[0]->Last->TotalLength + State.Column + 2 >
+ Style.ColumnLimit)
+ return false;
+
+ if (!DryRun) {
+ Whitespaces->replaceWhitespace(
+ *Previous.Children[0]->First,
+ /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,
+ /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
+ }
+ Penalty += formatLine(*Previous.Children[0], State.Column + 1, DryRun);
+
+ State.Column += 1 + Previous.Children[0]->Last->TotalLength;
+ return true;
+ }
+
+ ContinuationIndenter *Indenter;
+
+private:
+ WhitespaceManager *Whitespaces;
+ const FormatStyle &Style;
+ UnwrappedLineFormatter *BlockFormatter;
+};
- /// \brief Formats the line starting at \p State, simply keeping all of the
- /// input's line breaking decisions.
- void format(unsigned FirstIndent, const AnnotatedLine *Line) {
+/// \brief Formatter that keeps the existing line breaks.
+class NoColumnLimitLineFormatter : public LineFormatter {
+public:
+ NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
+ WhitespaceManager *Whitespaces,
+ const FormatStyle &Style,
+ UnwrappedLineFormatter *BlockFormatter)
+ : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
+
+ /// \brief Formats the line, simply keeping all of the input's line breaking
+ /// decisions.
+ unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+ bool DryRun) override {
+ assert(!DryRun);
LineState State =
- Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);
+ Indenter->getInitialState(FirstIndent, &Line, /*DryRun=*/false);
while (State.NextToken) {
bool Newline =
Indenter->mustBreak(State) ||
(Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
+ unsigned Penalty = 0;
+ formatChildren(State, Newline, /*DryRun=*/false, Penalty);
Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
}
+ return 0;
+ }
+};
+
+/// \brief Formatter that puts all tokens into a single line without breaks.
+class NoLineBreakFormatter : public LineFormatter {
+public:
+ NoLineBreakFormatter(ContinuationIndenter *Indenter,
+ WhitespaceManager *Whitespaces, const FormatStyle &Style,
+ UnwrappedLineFormatter *BlockFormatter)
+ : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
+
+ /// \brief Puts all tokens into a single line.
+ unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+ bool DryRun) {
+ unsigned Penalty = 0;
+ LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
+ while (State.NextToken) {
+ formatChildren(State, /*Newline=*/false, DryRun, Penalty);
+ Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
+ }
+ return Penalty;
+ }
+};
+
+/// \brief Finds the best way to break lines.
+class OptimizingLineFormatter : public LineFormatter {
+public:
+ OptimizingLineFormatter(ContinuationIndenter *Indenter,
+ WhitespaceManager *Whitespaces,
+ const FormatStyle &Style,
+ UnwrappedLineFormatter *BlockFormatter)
+ : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
+
+ /// \brief Formats the line by finding the best line breaks with line lengths
+ /// below the column limit.
+ unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+ bool DryRun) {
+ LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
+
+ // If the ObjC method declaration does not fit on a line, we should format
+ // it with one arg per line.
+ if (State.Line->Type == LT_ObjCMethodDecl)
+ State.Stack.back().BreakBeforeParameter = true;
+
+ // Find best solution in solution space.
+ return analyzeSolutionSpace(State, DryRun);
}
private:
- ContinuationIndenter *Indenter;
+ struct CompareLineStatePointers {
+ bool operator()(LineState *obj1, LineState *obj2) const {
+ return *obj1 < *obj2;
+ }
+ };
+
+ /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
+ ///
+ /// In case of equal penalties, we want to prefer states that were inserted
+ /// first. During state generation we make sure that we insert states first
+ /// that break the line as late as possible.
+ typedef std::pair<unsigned, unsigned> OrderedPenalty;
+
+ /// \brief An edge in the solution space from \c Previous->State to \c State,
+ /// inserting a newline dependent on the \c NewLine.
+ struct StateNode {
+ StateNode(const LineState &State, bool NewLine, StateNode *Previous)
+ : State(State), NewLine(NewLine), Previous(Previous) {}
+ LineState State;
+ bool NewLine;
+ StateNode *Previous;
+ };
+
+ /// \brief An item in the prioritized BFS search queue. The \c StateNode's
+ /// \c State has the given \c OrderedPenalty.
+ typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
+
+ /// \brief The BFS queue type.
+ typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
+ std::greater<QueueItem>> QueueType;
+
+ /// \brief Analyze the entire solution space starting from \p InitialState.
+ ///
+ /// This implements a variant of Dijkstra's algorithm on the graph that spans
+ /// the solution space (\c LineStates are the nodes). The algorithm tries to
+ /// find the shortest path (the one with lowest penalty) from \p InitialState
+ /// to a state where all tokens are placed. Returns the penalty.
+ ///
+ /// If \p DryRun is \c false, directly applies the changes.
+ unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {
+ std::set<LineState *, CompareLineStatePointers> Seen;
+
+ // Increasing count of \c StateNode items we have created. This is used to
+ // create a deterministic order independent of the container.
+ unsigned Count = 0;
+ QueueType Queue;
+
+ // Insert start element into queue.
+ StateNode *Node =
+ new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
+ Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
+ ++Count;
+
+ unsigned Penalty = 0;
+
+ // While not empty, take first element and follow edges.
+ while (!Queue.empty()) {
+ Penalty = Queue.top().first.first;
+ StateNode *Node = Queue.top().second;
+ if (!Node->State.NextToken) {
+ DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
+ break;
+ }
+ Queue.pop();
+
+ // Cut off the analysis of certain solutions if the analysis gets too
+ // complex. See description of IgnoreStackForComparison.
+ if (Count > 10000)
+ Node->State.IgnoreStackForComparison = true;
+
+ if (!Seen.insert(&Node->State).second)
+ // State already examined with lower penalty.
+ continue;
+
+ FormatDecision LastFormat = Node->State.NextToken->Decision;
+ if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
+ addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
+ if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
+ addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
+ }
+
+ if (Queue.empty()) {
+ // We were unable to find a solution, do nothing.
+ // FIXME: Add diagnostic?
+ DEBUG(llvm::dbgs() << "Could not find a solution.\n");
+ return 0;
+ }
+
+ // Reconstruct the solution.
+ if (!DryRun)
+ reconstructPath(InitialState, Queue.top().second);
+
+ DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
+ DEBUG(llvm::dbgs() << "---\n");
+
+ return Penalty;
+ }
+
+ /// \brief Add the following state to the analysis queue \c Queue.
+ ///
+ /// Assume the current state is \p PreviousNode and has been reached with a
+ /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
+ void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
+ bool NewLine, unsigned *Count, QueueType *Queue) {
+ if (NewLine && !Indenter->canBreak(PreviousNode->State))
+ return;
+ if (!NewLine && Indenter->mustBreak(PreviousNode->State))
+ return;
+
+ StateNode *Node = new (Allocator.Allocate())
+ StateNode(PreviousNode->State, NewLine, PreviousNode);
+ if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
+ return;
+
+ Penalty += Indenter->addTokenToState(Node->State, NewLine, true);
+
+ Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
+ ++(*Count);
+ }
+
+ /// \brief Applies the best formatting by reconstructing the path in the
+ /// solution space that leads to \c Best.
+ void reconstructPath(LineState &State, StateNode *Best) {
+ std::deque<StateNode *> Path;
+ // We do not need a break before the initial token.
+ while (Best->Previous) {
+ Path.push_front(Best);
+ Best = Best->Previous;
+ }
+ for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
+ I != E; ++I) {
+ unsigned Penalty = 0;
+ formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
+ Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
+
+ DEBUG({
+ printLineState((*I)->Previous->State);
+ if ((*I)->NewLine) {
+ llvm::dbgs() << "Penalty for placing "
+ << (*I)->Previous->State.NextToken->Tok.getName() << ": "
+ << Penalty << "\n";
+ }
+ });
+ }
+ }
+
+ llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
};
} // namespace
@@ -315,7 +797,7 @@ unsigned
UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool DryRun, int AdditionalIndent,
bool FixBadIndentation) {
- LineJoiner Joiner(Style);
+ LineJoiner Joiner(Style, Keywords, Lines);
// Try to look up already computed penalty in DryRun-mode.
std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
@@ -326,151 +808,93 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
assert(!Lines.empty());
unsigned Penalty = 0;
- std::vector<int> IndentForLevel;
- for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)
- IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
+ LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
+ AdditionalIndent);
const AnnotatedLine *PreviousLine = nullptr;
- for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
- E = Lines.end();
- I != E; ++I) {
- const AnnotatedLine &TheLine = **I;
- const FormatToken *FirstTok = TheLine.First;
- int Offset = getIndentOffset(*FirstTok);
-
- // Determine indent and try to merge multiple unwrapped lines.
- unsigned Indent;
- if (TheLine.InPPDirective) {
- Indent = TheLine.Level * Style.IndentWidth;
- } else {
- while (IndentForLevel.size() <= TheLine.Level)
- IndentForLevel.push_back(-1);
- IndentForLevel.resize(TheLine.Level + 1);
- Indent = getIndent(IndentForLevel, TheLine.Level);
- }
- unsigned LevelIndent = Indent;
- if (static_cast<int>(Indent) + Offset >= 0)
- Indent += Offset;
-
- // Merge multiple lines if possible.
- unsigned MergedLines = Joiner.tryFitMultipleLinesInOne(Indent, I, E);
- if (MergedLines > 0 && Style.ColumnLimit == 0) {
- // Disallow line merging if there is a break at the start of one of the
- // input lines.
- for (unsigned i = 0; i < MergedLines; ++i) {
- if (I[i + 1]->First->NewlinesBefore > 0)
- MergedLines = 0;
- }
- }
- if (!DryRun) {
- for (unsigned i = 0; i < MergedLines; ++i) {
- join(*I[i], *I[i + 1]);
- }
- }
- I += MergedLines;
-
+ const AnnotatedLine *NextLine = nullptr;
+ for (const AnnotatedLine *Line =
+ Joiner.getNextMergedLine(DryRun, IndentTracker);
+ Line; Line = NextLine) {
+ const AnnotatedLine &TheLine = *Line;
+ unsigned Indent = IndentTracker.getIndent();
bool FixIndentation =
- FixBadIndentation && (LevelIndent != FirstTok->OriginalColumn);
- if (TheLine.First->is(tok::eof)) {
- if (PreviousLine && PreviousLine->Affected && !DryRun) {
- // Remove the file's trailing whitespace.
- unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);
- Whitespaces->replaceWhitespace(*TheLine.First, Newlines,
- /*IndentLevel=*/0, /*Spaces=*/0,
- /*TargetColumn=*/0);
- }
- } else if (TheLine.Type != LT_Invalid &&
- (TheLine.Affected || FixIndentation)) {
- if (FirstTok->WhitespaceRange.isValid()) {
- if (!DryRun)
- formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level, Indent,
+ FixBadIndentation && (Indent != TheLine.First->OriginalColumn);
+ bool ShouldFormat = TheLine.Affected || FixIndentation;
+ // We cannot format this line; if the reason is that the line had a
+ // parsing error, remember that.
+ if (ShouldFormat && TheLine.Type == LT_Invalid && IncompleteFormat)
+ *IncompleteFormat = true;
+
+ if (ShouldFormat && TheLine.Type != LT_Invalid) {
+ if (!DryRun)
+ formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level, Indent,
+ TheLine.InPPDirective);
+
+ NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
+ unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);
+ bool FitsIntoOneLine =
+ TheLine.Last->TotalLength + Indent <= ColumnLimit ||
+ TheLine.Type == LT_ImportStatement;
+
+ if (Style.ColumnLimit == 0)
+ NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
+ .formatLine(TheLine, Indent, DryRun);
+ else if (FitsIntoOneLine)
+ Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)
+ .formatLine(TheLine, Indent, DryRun);
+ else
+ Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
+ .formatLine(TheLine, Indent, DryRun);
+ } else {
+ // If no token in the current line is affected, we still need to format
+ // affected children.
+ if (TheLine.ChildrenAffected)
+ format(TheLine.Children, DryRun);
+
+ // Adapt following lines on the current indent level to the same level
+ // unless the current \c AnnotatedLine is not at the beginning of a line.
+ bool StartsNewLine =
+ TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst;
+ if (StartsNewLine)
+ IndentTracker.adjustToUnmodifiedLine(TheLine);
+ if (!DryRun) {
+ bool ReformatLeadingWhitespace =
+ StartsNewLine && ((PreviousLine && PreviousLine->Affected) ||
+ TheLine.LeadingEmptyLinesAffected);
+ // Format the first token.
+ if (ReformatLeadingWhitespace)
+ formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level,
+ TheLine.First->OriginalColumn,
TheLine.InPPDirective);
- } else {
- Indent = LevelIndent = FirstTok->OriginalColumn;
- }
+ else
+ Whitespaces->addUntouchableToken(*TheLine.First,
+ TheLine.InPPDirective);
- // If everything fits on a single line, just put it there.
- unsigned ColumnLimit = Style.ColumnLimit;
- if (I + 1 != E) {
- AnnotatedLine *NextLine = I[1];
- if (NextLine->InPPDirective && !NextLine->First->HasUnescapedNewline)
- ColumnLimit = getColumnLimit(TheLine.InPPDirective);
- }
-
- if (TheLine.Last->TotalLength + Indent <= ColumnLimit ||
- TheLine.Type == LT_ImportStatement) {
- LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);
- while (State.NextToken) {
- formatChildren(State, /*Newline=*/false, /*DryRun=*/false, Penalty);
- Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
- }
- } else if (Style.ColumnLimit == 0) {
- // FIXME: Implement nested blocks for ColumnLimit = 0.
- NoColumnLimitFormatter Formatter(Indenter);
- if (!DryRun)
- Formatter.format(Indent, &TheLine);
- } else {
- Penalty += format(TheLine, Indent, DryRun);
- }
-
- if (!TheLine.InPPDirective)
- IndentForLevel[TheLine.Level] = LevelIndent;
- } else if (TheLine.ChildrenAffected) {
- format(TheLine.Children, DryRun);
- } else {
- // Format the first token if necessary, and notify the WhitespaceManager
- // about the unchanged whitespace.
- for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
- if (Tok == TheLine.First && (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
- unsigned LevelIndent = Tok->OriginalColumn;
- if (!DryRun) {
- // Remove trailing whitespace of the previous line.
- if ((PreviousLine && PreviousLine->Affected) ||
- TheLine.LeadingEmptyLinesAffected) {
- formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,
- TheLine.InPPDirective);
- } else {
- Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
- }
- }
-
- if (static_cast<int>(LevelIndent) - Offset >= 0)
- LevelIndent -= Offset;
- if (Tok->isNot(tok::comment) && !TheLine.InPPDirective)
- IndentForLevel[TheLine.Level] = LevelIndent;
- } else if (!DryRun) {
+ // Notify the WhitespaceManager about the unchanged whitespace.
+ for (FormatToken *Tok = TheLine.First->Next; Tok; Tok = Tok->Next)
Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
- }
}
+ NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
}
- if (!DryRun) {
- for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
- Tok->Finalized = true;
- }
- }
- PreviousLine = *I;
+ if (!DryRun)
+ markFinalized(TheLine.First);
+ PreviousLine = &TheLine;
}
PenaltyCache[CacheKey] = Penalty;
return Penalty;
}
-unsigned UnwrappedLineFormatter::format(const AnnotatedLine &Line,
- unsigned FirstIndent, bool DryRun) {
- LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
-
- // If the ObjC method declaration does not fit on a line, we should format
- // it with one arg per line.
- if (State.Line->Type == LT_ObjCMethodDecl)
- State.Stack.back().BreakBeforeParameter = true;
-
- // Find best solution in solution space.
- return analyzeSolutionSpace(State, DryRun);
-}
-
void UnwrappedLineFormatter::formatFirstToken(FormatToken &RootToken,
const AnnotatedLine *PreviousLine,
unsigned IndentLevel,
unsigned Indent,
bool InPPDirective) {
+ if (RootToken.is(tok::eof)) {
+ unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
+ Whitespaces->replaceWhitespace(RootToken, Newlines, /*IndentLevel=*/0,
+ /*Spaces=*/0, /*TargetColumn=*/0);
+ return;
+ }
unsigned Newlines =
std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
// Remove empty lines before "}" where applicable.
@@ -496,7 +920,8 @@ void UnwrappedLineFormatter::formatFirstToken(FormatToken &RootToken,
++Newlines;
// Remove empty lines after access specifiers.
- if (PreviousLine && PreviousLine->First->isAccessSpecifier())
+ if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
+ (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline))
Newlines = std::min(1u, Newlines);
Whitespaces->replaceWhitespace(RootToken, Newlines, IndentLevel, Indent,
@@ -504,202 +929,21 @@ void UnwrappedLineFormatter::formatFirstToken(FormatToken &RootToken,
!RootToken.HasUnescapedNewline);
}
-/// \brief Get the indent of \p Level from \p IndentForLevel.
-///
-/// \p IndentForLevel must contain the indent for the level \c l
-/// at \p IndentForLevel[l], or a value < 0 if the indent for
-/// that level is unknown.
-unsigned UnwrappedLineFormatter::getIndent(ArrayRef<int> IndentForLevel,
- unsigned Level) {
- if (IndentForLevel[Level] != -1)
- return IndentForLevel[Level];
- if (Level == 0)
- return 0;
- return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
-}
-
-void UnwrappedLineFormatter::join(AnnotatedLine &A, const AnnotatedLine &B) {
- assert(!A.Last->Next);
- assert(!B.First->Previous);
- if (B.Affected)
- A.Affected = true;
- A.Last->Next = B.First;
- B.First->Previous = A.Last;
- B.First->CanBreakBefore = true;
- unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
- for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
- Tok->TotalLength += LengthA;
- A.Last = Tok;
- }
-}
-
-unsigned UnwrappedLineFormatter::analyzeSolutionSpace(LineState &InitialState,
- bool DryRun) {
- std::set<LineState *, CompareLineStatePointers> Seen;
-
- // Increasing count of \c StateNode items we have created. This is used to
- // create a deterministic order independent of the container.
- unsigned Count = 0;
- QueueType Queue;
-
- // Insert start element into queue.
- StateNode *Node =
- new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
- Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
- ++Count;
-
- unsigned Penalty = 0;
-
- // While not empty, take first element and follow edges.
- while (!Queue.empty()) {
- Penalty = Queue.top().first.first;
- StateNode *Node = Queue.top().second;
- if (!Node->State.NextToken) {
- DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
- break;
- }
- Queue.pop();
-
- // Cut off the analysis of certain solutions if the analysis gets too
- // complex. See description of IgnoreStackForComparison.
- if (Count > 10000)
- Node->State.IgnoreStackForComparison = true;
-
- if (!Seen.insert(&Node->State).second)
- // State already examined with lower penalty.
- continue;
-
- FormatDecision LastFormat = Node->State.NextToken->Decision;
- if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
- addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
- if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
- addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
- }
-
- if (Queue.empty()) {
- // We were unable to find a solution, do nothing.
- // FIXME: Add diagnostic?
- DEBUG(llvm::dbgs() << "Could not find a solution.\n");
- return 0;
- }
-
- // Reconstruct the solution.
- if (!DryRun)
- reconstructPath(InitialState, Queue.top().second);
-
- DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
- DEBUG(llvm::dbgs() << "---\n");
-
- return Penalty;
-}
-
-#ifndef NDEBUG
-static void printLineState(const LineState &State) {
- llvm::dbgs() << "State: ";
- for (const ParenState &P : State.Stack) {
- llvm::dbgs() << P.Indent << "|" << P.LastSpace << "|" << P.NestedBlockIndent
- << " ";
- }
- llvm::dbgs() << State.NextToken->TokenText << "\n";
-}
-#endif
-
-void UnwrappedLineFormatter::reconstructPath(LineState &State,
- StateNode *Current) {
- std::deque<StateNode *> Path;
- // We do not need a break before the initial token.
- while (Current->Previous) {
- Path.push_front(Current);
- Current = Current->Previous;
- }
- for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
- I != E; ++I) {
- unsigned Penalty = 0;
- formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
- Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
-
- DEBUG({
- printLineState((*I)->Previous->State);
- if ((*I)->NewLine) {
- llvm::dbgs() << "Penalty for placing "
- << (*I)->Previous->State.NextToken->Tok.getName() << ": "
- << Penalty << "\n";
- }
- });
- }
-}
-
-void UnwrappedLineFormatter::addNextStateToQueue(unsigned Penalty,
- StateNode *PreviousNode,
- bool NewLine, unsigned *Count,
- QueueType *Queue) {
- if (NewLine && !Indenter->canBreak(PreviousNode->State))
- return;
- if (!NewLine && Indenter->mustBreak(PreviousNode->State))
- return;
-
- StateNode *Node = new (Allocator.Allocate())
- StateNode(PreviousNode->State, NewLine, PreviousNode);
- if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
- return;
-
- Penalty += Indenter->addTokenToState(Node->State, NewLine, true);
-
- Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
- ++(*Count);
-}
-
-bool UnwrappedLineFormatter::formatChildren(LineState &State, bool NewLine,
- bool DryRun, unsigned &Penalty) {
- FormatToken &Previous = *State.NextToken->Previous;
- const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
- if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->BlockKind != BK_Block ||
- Previous.Children.size() == 0)
- // The previous token does not open a block. Nothing to do. We don't
- // assert so that we can simply call this function for all tokens.
- return true;
-
- if (NewLine) {
- int AdditionalIndent = State.Stack.back().Indent -
- Previous.Children[0]->Level * Style.IndentWidth;
-
- Penalty += format(Previous.Children, DryRun, AdditionalIndent,
- /*FixBadIndentation=*/true);
- return true;
- }
-
- if (Previous.Children[0]->First->MustBreakBefore)
- return false;
-
- // Cannot merge multiple statements into a single line.
- if (Previous.Children.size() > 1)
- return false;
-
- // Cannot merge into one line if this line ends on a comment.
- if (Previous.is(tok::comment))
- return false;
-
- // We can't put the closing "}" on a line with a trailing comment.
- if (Previous.Children[0]->Last->isTrailingComment())
- return false;
-
- // If the child line exceeds the column limit, we wouldn't want to merge it.
- // We add +2 for the trailing " }".
- if (Style.ColumnLimit > 0 &&
- Previous.Children[0]->Last->TotalLength + State.Column + 2 >
- Style.ColumnLimit)
- return false;
-
- if (!DryRun) {
- Whitespaces->replaceWhitespace(
- *Previous.Children[0]->First,
- /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,
- /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
- }
- Penalty += format(*Previous.Children[0], State.Column + 1, DryRun);
-
- State.Column += 1 + Previous.Children[0]->Last->TotalLength;
- return true;
+unsigned
+UnwrappedLineFormatter::getColumnLimit(bool InPPDirective,
+ const AnnotatedLine *NextLine) const {
+ // In preprocessor directives reserve two chars for trailing " \" if the
+ // next line continues the preprocessor directive.
+ bool ContinuesPPDirective =
+ InPPDirective &&
+ // If there is no next line, this is likely a child line and the parent
+ // continues the preprocessor directive.
+ (!NextLine ||
+ (NextLine->InPPDirective &&
+ // If there is an unescaped newline between this line and the next, the
+ // next line starts a new preprocessor directive.
+ !NextLine->First->HasUnescapedNewline));
+ return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0);
}
} // namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
index 3ae6dbc..478617d 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
@@ -32,135 +32,40 @@ class UnwrappedLineFormatter {
public:
UnwrappedLineFormatter(ContinuationIndenter *Indenter,
WhitespaceManager *Whitespaces,
- const FormatStyle &Style)
- : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style) {}
+ const FormatStyle &Style,
+ const AdditionalKeywords &Keywords,
+ bool *IncompleteFormat)
+ : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
+ Keywords(Keywords), IncompleteFormat(IncompleteFormat) {}
- unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
- int AdditionalIndent = 0, bool FixBadIndentation = false);
+ /// \brief Format the current block and return the penalty.
+ unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
+ bool DryRun = false, int AdditionalIndent = 0,
+ bool FixBadIndentation = false);
private:
- /// \brief Formats an \c AnnotatedLine and returns the penalty.
- ///
- /// If \p DryRun is \c false, directly applies the changes.
- unsigned format(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun);
-
- /// \brief An edge in the solution space from \c Previous->State to \c State,
- /// inserting a newline dependent on the \c NewLine.
- struct StateNode {
- StateNode(const LineState &State, bool NewLine, StateNode *Previous)
- : State(State), NewLine(NewLine), Previous(Previous) {}
- LineState State;
- bool NewLine;
- StateNode *Previous;
- };
-
- /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
- ///
- /// In case of equal penalties, we want to prefer states that were inserted
- /// first. During state generation we make sure that we insert states first
- /// that break the line as late as possible.
- typedef std::pair<unsigned, unsigned> OrderedPenalty;
-
- /// \brief An item in the prioritized BFS search queue. The \c StateNode's
- /// \c State has the given \c OrderedPenalty.
- typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
-
- /// \brief The BFS queue type.
- typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
- std::greater<QueueItem> > QueueType;
-
- /// \brief Get the offset of the line relatively to the level.
- ///
- /// For example, 'public:' labels in classes are offset by 1 or 2
- /// characters to the left from their level.
- int getIndentOffset(const FormatToken &RootToken) {
- if (Style.Language == FormatStyle::LK_Java)
- return 0;
- if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
- return Style.AccessModifierOffset;
- return 0;
- }
-
/// \brief Add a new line and the required indent before the first Token
/// of the \c UnwrappedLine if there was no structural parsing error.
void formatFirstToken(FormatToken &RootToken,
const AnnotatedLine *PreviousLine, unsigned IndentLevel,
unsigned Indent, bool InPPDirective);
- /// \brief Get the indent of \p Level from \p IndentForLevel.
- ///
- /// \p IndentForLevel must contain the indent for the level \c l
- /// at \p IndentForLevel[l], or a value < 0 if the indent for
- /// that level is unknown.
- unsigned getIndent(ArrayRef<int> IndentForLevel, unsigned Level);
-
- void join(AnnotatedLine &A, const AnnotatedLine &B);
-
- unsigned getColumnLimit(bool InPPDirective) const {
- // In preprocessor directives reserve two chars for trailing " \"
- return Style.ColumnLimit - (InPPDirective ? 2 : 0);
- }
-
- struct CompareLineStatePointers {
- bool operator()(LineState *obj1, LineState *obj2) const {
- return *obj1 < *obj2;
- }
- };
-
- /// \brief Analyze the entire solution space starting from \p InitialState.
- ///
- /// This implements a variant of Dijkstra's algorithm on the graph that spans
- /// the solution space (\c LineStates are the nodes). The algorithm tries to
- /// find the shortest path (the one with lowest penalty) from \p InitialState
- /// to a state where all tokens are placed. Returns the penalty.
- ///
- /// If \p DryRun is \c false, directly applies the changes.
- unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false);
-
- void reconstructPath(LineState &State, StateNode *Current);
-
- /// \brief Add the following state to the analysis queue \c Queue.
- ///
- /// Assume the current state is \p PreviousNode and has been reached with a
- /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
- void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
- bool NewLine, unsigned *Count, QueueType *Queue);
-
- /// \brief If the \p State's next token is an r_brace closing a nested block,
- /// format the nested block before it.
- ///
- /// Returns \c true if all children could be placed successfully and adapts
- /// \p Penalty as well as \p State. If \p DryRun is false, also directly
- /// creates changes using \c Whitespaces.
- ///
- /// The crucial idea here is that children always get formatted upon
- /// encountering the closing brace right after the nested block. Now, if we
- /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
- /// \c false), the entire block has to be kept on the same line (which is only
- /// possible if it fits on the line, only contains a single statement, etc.
- ///
- /// If \p NewLine is true, we format the nested block on separate lines, i.e.
- /// break after the "{", format all lines with correct indentation and the put
- /// the closing "}" on yet another new line.
- ///
- /// This enables us to keep the simple structure of the
- /// \c UnwrappedLineFormatter, where we only have two options for each token:
- /// break or don't break.
- bool formatChildren(LineState &State, bool NewLine, bool DryRun,
- unsigned &Penalty);
-
- ContinuationIndenter *Indenter;
- WhitespaceManager *Whitespaces;
- FormatStyle Style;
-
- llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
+ /// \brief Returns the column limit for a line, taking into account whether we
+ /// need an escaped newline due to a continued preprocessor directive.
+ unsigned getColumnLimit(bool InPPDirective,
+ const AnnotatedLine *NextLine) const;
// Cache to store the penalty of formatting a vector of AnnotatedLines
// starting from a specific additional offset. Improves performance if there
// are many nested blocks.
std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
unsigned> PenaltyCache;
+
+ ContinuationIndenter *Indenter;
+ WhitespaceManager *Whitespaces;
+ const FormatStyle &Style;
+ const AdditionalKeywords &Keywords;
+ bool *IncompleteFormat;
};
} // end namespace format
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
index ec04af5..97fd98e 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
@@ -14,7 +14,9 @@
//===----------------------------------------------------------------------===//
#include "UnwrappedLineParser.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "format-parser"
@@ -56,22 +58,20 @@ private:
class ScopedMacroState : public FormatTokenSource {
public:
ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
- FormatToken *&ResetToken, bool &StructuralError)
+ FormatToken *&ResetToken)
: Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
- StructuralError(StructuralError),
- PreviousStructuralError(StructuralError), Token(nullptr) {
+ Token(nullptr) {
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
}
- ~ScopedMacroState() {
+ ~ScopedMacroState() override {
TokenSource = PreviousTokenSource;
ResetToken = Token;
Line.InPPDirective = false;
Line.Level = PreviousLineLevel;
- StructuralError = PreviousStructuralError;
}
FormatToken *getNextToken() override {
@@ -110,8 +110,6 @@ private:
FormatToken *&ResetToken;
unsigned PreviousLineLevel;
FormatTokenSource *PreviousTokenSource;
- bool &StructuralError;
- bool PreviousStructuralError;
FormatToken *Token;
};
@@ -206,9 +204,8 @@ UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
ArrayRef<FormatToken *> Tokens,
UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
- CurrentLines(&Lines), StructuralError(false), Style(Style),
- Keywords(Keywords), Tokens(nullptr), Callback(Callback),
- AllTokens(Tokens), PPBranchLevel(-1) {}
+ CurrentLines(&Lines), Style(Style), Keywords(Keywords), Tokens(nullptr),
+ Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1) {}
void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
@@ -219,11 +216,10 @@ void UnwrappedLineParser::reset() {
PreprocessorDirectives.clear();
CurrentLines = &Lines;
DeclarationScopeStack.clear();
- StructuralError = false;
PPStack.clear();
}
-bool UnwrappedLineParser::parse() {
+void UnwrappedLineParser::parse() {
IndexedTokenSource TokenSource(AllTokens);
do {
DEBUG(llvm::dbgs() << "----\n");
@@ -255,14 +251,15 @@ bool UnwrappedLineParser::parse() {
assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
}
} while (!PPLevelBranchIndex.empty());
-
- return StructuralError;
}
void UnwrappedLineParser::parseFile() {
- ScopedDeclarationState DeclarationState(
- *Line, DeclarationScopeStack,
- /*MustBeDeclaration=*/ !Line->InPPDirective);
+ // The top-level context in a file always has declarations, except for pre-
+ // processor directives and JavaScript files.
+ bool MustBeDeclaration =
+ !Line->InPPDirective && Style.Language != FormatStyle::LK_JavaScript;
+ ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
+ MustBeDeclaration);
parseLevel(/*HasOpeningBrace=*/false);
// Make sure to format the remaining tokens.
flushComments(true);
@@ -272,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();
@@ -286,7 +290,6 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
case tok::r_brace:
if (HasOpeningBrace)
return;
- StructuralError = true;
nextToken();
addUnwrappedLine();
break;
@@ -305,7 +308,7 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
} while (!eof());
}
-void UnwrappedLineParser::calculateBraceTypes() {
+void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// We'll parse forward through the tokens until we hit
// a closing brace or eof - note that getNextToken() will
// parse macros, so this will magically work inside macro
@@ -328,6 +331,7 @@ void UnwrappedLineParser::calculateBraceTypes() {
switch (Tok->Tok.getKind()) {
case tok::l_brace:
+ Tok->BlockKind = BK_Unknown;
LBraceStack.push_back(Tok);
break;
case tok::r_brace:
@@ -351,9 +355,11 @@ void UnwrappedLineParser::calculateBraceTypes() {
//
// We exclude + and - as they can be ObjC visibility modifiers.
ProbablyBracedList =
- NextTok->isOneOf(tok::comma, tok::semi, tok::period, tok::colon,
+ NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_paren, tok::ellipsis) ||
+ (NextTok->is(tok::semi) &&
+ (!ExpectClassBody || LBraceStack.size() != 1)) ||
(NextTok->isBinaryOperator() && !NextIsObjCMethod);
}
if (ProbablyBracedList) {
@@ -374,6 +380,7 @@ void UnwrappedLineParser::calculateBraceTypes() {
case tok::kw_for:
case tok::kw_switch:
case tok::kw_try:
+ case tok::kw___try:
if (!LBraceStack.empty())
LBraceStack.back()->BlockKind = BK_Block;
break;
@@ -393,10 +400,16 @@ void UnwrappedLineParser::calculateBraceTypes() {
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,19 +418,23 @@ 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;
- StructuralError = true;
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;
}
-static bool IsGoogScope(const UnwrappedLine &Line) {
+static bool isGoogScope(const UnwrappedLine &Line) {
// FIXME: Closure-library specific stuff should not be hard-coded but be
// configurable.
if (Line.Tokens.size() < 4)
@@ -440,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;
@@ -453,12 +472,13 @@ void UnwrappedLineParser::parseChildBlock() {
nextToken();
{
bool GoogScope =
- Style.Language == FormatStyle::LK_JavaScript && IsGoogScope(*Line);
+ Style.Language == FormatStyle::LK_JavaScript && isGoogScope(*Line);
ScopedLineState LineState(*this);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/false);
Line->Level += GoogScope ? 0 : 1;
parseLevel(/*HasOpeningBrace=*/true);
+ flushComments(isOnNewLine(*FormatTok));
Line->Level -= GoogScope ? 0 : 1;
}
nextToken();
@@ -466,7 +486,7 @@ void UnwrappedLineParser::parseChildBlock() {
void UnwrappedLineParser::parsePPDirective() {
assert(FormatTok->Tok.is(tok::hash) && "'#' expected");
- ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError);
+ ScopedMacroState MacroState(*Line, Tokens, FormatTok);
nextToken();
if (!FormatTok->Tok.getIdentifierInfo()) {
@@ -549,6 +569,7 @@ void UnwrappedLineParser::conditionalCompilationEnd() {
void UnwrappedLineParser::parsePPIf(bool IfDef) {
nextToken();
bool IsLiteralFalse = (FormatTok->Tok.isLiteral() &&
+ FormatTok->Tok.getLiteralData() != nullptr &&
StringRef(FormatTok->Tok.getLiteralData(),
FormatTok->Tok.getLength()) == "0") ||
FormatTok->Tok.is(tok::kw_false);
@@ -602,7 +623,7 @@ void UnwrappedLineParser::parsePPUnknown() {
// Here we blacklist certain tokens that are not usually the first token in an
// unwrapped line. This is used in attempt to distinguish macro calls without
// trailing semicolons from other constructs split to several lines.
-bool tokenCanStartNewLine(clang::Token Tok) {
+static bool tokenCanStartNewLine(const clang::Token &Tok) {
// Semicolon can be a null-statement, l_square can be a start of a macro or
// a C++11 attribute, but this doesn't seem to be common.
return Tok.isNot(tok::semi) && Tok.isNot(tok::l_brace) &&
@@ -655,6 +676,21 @@ void UnwrappedLineParser::parseStructuralElement() {
nextToken();
addUnwrappedLine();
return;
+ case tok::objc_autoreleasepool:
+ nextToken();
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ addUnwrappedLine();
+ parseBlock(/*MustBeDeclaration=*/false);
+ }
+ addUnwrappedLine();
+ return;
+ case tok::objc_try:
+ // This branch isn't strictly necessary (the kw_try case below would
+ // do this too after the tok::at is parsed above). But be explicit.
+ parseTryCatch();
+ return;
default:
break;
}
@@ -662,10 +698,13 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_asm:
nextToken();
if (FormatTok->is(tok::l_brace)) {
+ FormatTok->Type = TT_InlineASMBrace;
nextToken();
while (FormatTok && FormatTok->isNot(tok::eof)) {
if (FormatTok->is(tok::r_brace)) {
+ FormatTok->Type = TT_InlineASMBrace;
nextToken();
+ addUnwrappedLine();
break;
}
FormatTok->Finalized = true;
@@ -686,7 +725,8 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_public:
case tok::kw_protected:
case tok::kw_private:
- if (Style.Language == FormatStyle::LK_Java)
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript)
nextToken();
else
parseAccessSpecifier();
@@ -712,6 +752,7 @@ void UnwrappedLineParser::parseStructuralElement() {
parseCaseLabel();
return;
case tok::kw_try:
+ case tok::kw___try:
parseTryCatch();
return;
case tok::kw_extern:
@@ -725,11 +766,35 @@ void UnwrappedLineParser::parseStructuralElement() {
}
}
break;
+ case tok::kw_export:
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ parseJavaScriptEs6ImportExport();
+ return;
+ }
+ break;
case tok::identifier:
- if (FormatTok->IsForEachMacro) {
+ if (FormatTok->is(TT_ForEachMacro)) {
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();
+ return;
+ }
+ if (FormatTok->is(Keywords.kw_signals)) {
+ nextToken();
+ if (FormatTok->is(tok::colon)) {
+ nextToken();
+ addUnwrappedLine();
+ }
+ return;
+ }
// In all other cases, parse the declaration.
break;
default:
@@ -743,7 +808,15 @@ void UnwrappedLineParser::parseStructuralElement() {
parseBracedList();
break;
case tok::kw_enum:
+ // parseEnum falls through and does not yet add an unwrapped line as an
+ // enum definition can start a structural element.
parseEnum();
+ // This does not apply for Java and JavaScript.
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) {
+ addUnwrappedLine();
+ return;
+ }
break;
case tok::kw_typedef:
nextToken();
@@ -754,9 +827,15 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_struct:
case tok::kw_union:
case tok::kw_class:
+ // parseRecord falls through and does not yet add an unwrapped line as a
+ // record declaration or definition can start a structural element.
parseRecord();
- // A record declaration or definition is always the start of a structural
- // element.
+ // This does not apply for Java and JavaScript.
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) {
+ addUnwrappedLine();
+ return;
+ }
break;
case tok::period:
nextToken();
@@ -806,27 +885,48 @@ void UnwrappedLineParser::parseStructuralElement() {
parseTryCatch();
return;
case tok::identifier: {
- StringRef Text = FormatTok->TokenText;
+ 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 && Text == "function" &&
- Line->Tokens.size() > 0) {
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->is(Keywords.kw_function) && Line->Tokens.size() > 0) {
tryToParseJSFunction();
break;
}
+ if ((Style.Language == FormatStyle::LK_JavaScript ||
+ Style.Language == FormatStyle::LK_Java) &&
+ FormatTok->is(Keywords.kw_interface)) {
+ parseRecord();
+ addUnwrappedLine();
+ return;
+ }
+
+ StringRef Text = FormatTok->TokenText;
nextToken();
- if (Line->Tokens.size() == 1) {
- if (FormatTok->Tok.is(tok::colon)) {
+ if (Line->Tokens.size() == 1 &&
+ // JS doesn't have macros, and within classes colons indicate fields,
+ // not labels.
+ Style.Language != FormatStyle::LK_JavaScript) {
+ if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {
parseLabel();
return;
}
// Recognize function-like macro usages without trailing semicolon as
- // well as free-standing macrose like Q_OBJECT.
+ // well as free-standing macros like Q_OBJECT.
bool FunctionLike = FormatTok->is(tok::l_paren);
if (FunctionLike)
parseParens();
- if (FormatTok->NewlinesBefore > 0 &&
- (Text.size() >= 5 || FunctionLike) &&
+
+ bool FollowedByNewline =
+ CommentsBeforeNextToken.empty()
+ ? FormatTok->NewlinesBefore > 0
+ : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
+
+ if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
tokenCanStartNewLine(FormatTok->Tok) && Text == Text.upper()) {
addUnwrappedLine();
return;
@@ -835,6 +935,16 @@ void UnwrappedLineParser::parseStructuralElement() {
break;
}
case tok::equal:
+ // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
+ // TT_JsFatArrow. The always start an expression or a child block if
+ // followed by a curly.
+ if (FormatTok->is(TT_JsFatArrow)) {
+ nextToken();
+ if (FormatTok->is(tok::l_brace))
+ parseChildBlock();
+ break;
+ }
+
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
parseBracedList();
@@ -843,6 +953,9 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::l_square:
parseSquare();
break;
+ case tok::kw_new:
+ parseNew();
+ break;
default:
nextToken();
break;
@@ -851,6 +964,10 @@ void UnwrappedLineParser::parseStructuralElement() {
}
bool UnwrappedLineParser::tryToParseLambda() {
+ if (Style.Language != FormatStyle::LK_Cpp) {
+ nextToken();
+ return false;
+ }
// FIXME: This is a dirty way to access the previous token. Find a better
// solution.
if (!Line->Tokens.empty() &&
@@ -889,7 +1006,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
nextToken();
break;
case tok::arrow:
- FormatTok->Type = TT_TrailingReturnArrow;
+ FormatTok->Type = TT_LambdaArrow;
nextToken();
break;
default:
@@ -952,19 +1069,27 @@ void UnwrappedLineParser::tryToParseJSFunction() {
// Consume function name.
if (FormatTok->is(tok::identifier))
- nextToken();
+ nextToken();
if (FormatTok->isNot(tok::l_paren))
return;
- nextToken();
- while (FormatTok->isNot(tok::l_brace)) {
- // Err on the side of caution in order to avoid consuming the full file in
- // case of incomplete code.
- if (!FormatTok->isOneOf(tok::identifier, tok::comma, tok::r_paren,
- tok::comment))
- return;
+
+ // Parse formal parameter list.
+ parseParens();
+
+ if (FormatTok->is(tok::colon)) {
+ // Parse a type definition.
nextToken();
+
+ // Eat the type declaration. For braced inline object types, balance braces,
+ // otherwise just parse until finding an l_brace for the function body.
+ if (FormatTok->is(tok::l_brace))
+ tryToParseBracedList();
+ else
+ while (FormatTok->isNot(tok::l_brace) && !eof())
+ nextToken();
}
+
parseChildBlock();
}
@@ -985,10 +1110,20 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
// replace this by using parseAssigmentExpression() inside.
do {
- if (Style.Language == FormatStyle::LK_JavaScript &&
- FormatTok->is(Keywords.kw_function)) {
- tryToParseJSFunction();
- continue;
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (FormatTok->is(Keywords.kw_function)) {
+ tryToParseJSFunction();
+ continue;
+ }
+ if (FormatTok->is(TT_JsFatArrow)) {
+ nextToken();
+ // Fat arrows can be followed by simple expressions or by child blocks
+ // in curly braces.
+ if (FormatTok->is(tok::l_brace)) {
+ parseChildBlock();
+ continue;
+ }
+ }
}
switch (FormatTok->Tok.getKind()) {
case tok::caret:
@@ -1006,6 +1141,16 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
FormatTok->BlockKind = BK_BracedInit;
parseBracedList();
break;
+ case tok::l_paren:
+ parseParens();
+ // JavaScript can just have free standing methods and getters/setters in
+ // object literals. Detect them by a "{" following ")".
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (FormatTok->is(tok::l_brace))
+ parseChildBlock();
+ break;
+ }
+ break;
case tok::r_brace:
nextToken();
return !HasError;
@@ -1046,9 +1191,8 @@ void UnwrappedLineParser::parseParens() {
tryToParseLambda();
break;
case tok::l_brace:
- if (!tryToParseBracedList()) {
+ if (!tryToParseBracedList())
parseChildBlock();
- }
break;
case tok::at:
nextToken();
@@ -1088,9 +1232,8 @@ void UnwrappedLineParser::parseSquare() {
parseSquare();
break;
case tok::l_brace: {
- if (!tryToParseBracedList()) {
+ if (!tryToParseBracedList())
parseChildBlock();
- }
break;
}
case tok::at:
@@ -1148,7 +1291,7 @@ void UnwrappedLineParser::parseIfThenElse() {
}
void UnwrappedLineParser::parseTryCatch() {
- assert(FormatTok->is(tok::kw_try) && "'try' expected");
+ assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
nextToken();
bool NeedsUnwrappedLine = false;
if (FormatTok->is(tok::colon)) {
@@ -1158,8 +1301,6 @@ void UnwrappedLineParser::parseTryCatch() {
nextToken();
if (FormatTok->is(tok::l_paren))
parseParens();
- else
- StructuralError = true;
if (FormatTok->is(tok::comma))
nextToken();
}
@@ -1182,23 +1323,29 @@ void UnwrappedLineParser::parseTryCatch() {
// The C++ standard requires a compound-statement after a try.
// If there's none, we try to assume there's a structuralElement
// and try to continue.
- StructuralError = true;
addUnwrappedLine();
++Line->Level;
parseStructuralElement();
--Line->Level;
}
- while (FormatTok->is(tok::kw_catch) ||
- ((Style.Language == FormatStyle::LK_Java ||
- Style.Language == FormatStyle::LK_JavaScript) &&
- FormatTok->is(Keywords.kw_finally))) {
+ while (1) {
+ if (FormatTok->is(tok::at))
+ nextToken();
+ if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,
+ tok::kw___finally) ||
+ ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ FormatTok->is(Keywords.kw_finally)) ||
+ (FormatTok->Tok.isObjCAtKeyword(tok::objc_catch) ||
+ FormatTok->Tok.isObjCAtKeyword(tok::objc_finally))))
+ break;
nextToken();
while (FormatTok->isNot(tok::l_brace)) {
if (FormatTok->is(tok::l_paren)) {
parseParens();
continue;
}
- if (FormatTok->isOneOf(tok::semi, tok::r_brace))
+ if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof))
return;
nextToken();
}
@@ -1242,9 +1389,33 @@ void UnwrappedLineParser::parseNamespace() {
// FIXME: Add error handling.
}
+void UnwrappedLineParser::parseNew() {
+ assert(FormatTok->is(tok::kw_new) && "'new' expected");
+ nextToken();
+ if (Style.Language != FormatStyle::LK_Java)
+ return;
+
+ // In Java, we can parse everything up to the parens, which aren't optional.
+ do {
+ // There should not be a ;, { or } before the new's open paren.
+ if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
+ return;
+
+ // Consume the parens.
+ if (FormatTok->is(tok::l_paren)) {
+ parseParens();
+
+ // If there is a class body of an anonymous class, consume that as child.
+ if (FormatTok->is(tok::l_brace))
+ parseChildBlock();
+ return;
+ }
+ nextToken();
+ } while (!eof());
+}
+
void UnwrappedLineParser::parseForOrWhileLoop() {
- assert((FormatTok->Tok.is(tok::kw_for) || FormatTok->Tok.is(tok::kw_while) ||
- FormatTok->IsForEachMacro) &&
+ assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) &&
"'for', 'while' or foreach macro expected");
nextToken();
if (FormatTok->Tok.is(tok::l_paren))
@@ -1304,6 +1475,8 @@ void UnwrappedLineParser::parseLabel() {
}
addUnwrappedLine();
} else {
+ if (FormatTok->is(tok::semi))
+ nextToken();
addUnwrappedLine();
}
Line->Level = OldLineLevel;
@@ -1338,8 +1511,7 @@ void UnwrappedLineParser::parseSwitch() {
void UnwrappedLineParser::parseAccessSpecifier() {
nextToken();
// Understand Qt's slots.
- if (FormatTok->is(tok::identifier) &&
- (FormatTok->TokenText == "slots" || FormatTok->TokenText == "Q_SLOTS"))
+ if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
nextToken();
// Otherwise, we don't know what it is, and we'd better keep the next token.
if (FormatTok->Tok.is(tok::colon))
@@ -1355,6 +1527,7 @@ void UnwrappedLineParser::parseEnum() {
// Eat up enum class ...
if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
nextToken();
+
while (FormatTok->Tok.getIdentifierInfo() ||
FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
tok::greater, tok::comma, tok::question)) {
@@ -1362,8 +1535,14 @@ void UnwrappedLineParser::parseEnum() {
// We can have macros or attributes in between 'enum' and the enum name.
if (FormatTok->is(tok::l_paren))
parseParens();
- if (FormatTok->is(tok::identifier))
+ if (FormatTok->is(tok::identifier)) {
nextToken();
+ // If there are two identifiers in a row, this is likely an elaborate
+ // return type. In Java, this can be "implements", etc.
+ if (Style.Language == FormatStyle::LK_Cpp &&
+ FormatTok->is(tok::identifier))
+ return;
+ }
}
// Just a declaration or something is wrong.
@@ -1385,8 +1564,8 @@ void UnwrappedLineParser::parseEnum() {
addUnwrappedLine();
}
- // We fall through to parsing a structural element afterwards, so that in
- // enum A {} n, m;
+ // There is no addUnwrappedLine() here so that we fall through to parsing a
+ // structural element afterwards. Thus, in "enum A {} n, m;",
// "} n, m;" will end up in one unwrapped line.
}
@@ -1455,37 +1634,44 @@ void UnwrappedLineParser::parseJavaEnumBody() {
void UnwrappedLineParser::parseRecord() {
const FormatToken &InitialToken = *FormatTok;
nextToken();
- if (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw___attribute,
- tok::kw___declspec, tok::kw_alignas)) {
+
+ // The actual identifier can be a nested name specifier, and in macros
+ // it is often token-pasted.
+ while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
+ tok::kw___attribute, tok::kw___declspec,
+ tok::kw_alignas) ||
+ ((Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ FormatTok->isOneOf(tok::period, tok::comma))) {
+ bool IsNonMacroIdentifier =
+ FormatTok->is(tok::identifier) &&
+ FormatTok->TokenText != FormatTok->TokenText.upper();
nextToken();
// We can have macros or attributes in between 'class' and the class name.
- if (FormatTok->Tok.is(tok::l_paren)) {
+ if (!IsNonMacroIdentifier && FormatTok->Tok.is(tok::l_paren))
parseParens();
- }
- // The actual identifier can be a nested name specifier, and in macros
- // it is often token-pasted.
- while (FormatTok->is(tok::identifier) || FormatTok->is(tok::coloncolon) ||
- FormatTok->is(tok::hashhash) ||
- (Style.Language == FormatStyle::LK_Java &&
- FormatTok->isOneOf(tok::period, tok::comma)))
- nextToken();
+ }
- // Note that parsing away template declarations here leads to incorrectly
- // accepting function declarations as record declarations.
- // In general, we cannot solve this problem. Consider:
- // class A<int> B() {}
- // which can be a function definition or a class definition when B() is a
- // macro. If we find enough real-world cases where this is a problem, we
- // can parse for the 'template' keyword in the beginning of the statement,
- // and thus rule out the record production in case there is no template
- // (this would still leave us with an ambiguity between template function
- // and class declarations).
- if (FormatTok->Tok.is(tok::colon) || FormatTok->Tok.is(tok::less)) {
- while (!eof() && FormatTok->Tok.isNot(tok::l_brace)) {
- if (FormatTok->Tok.is(tok::semi))
- return;
- nextToken();
+ // Note that parsing away template declarations here leads to incorrectly
+ // accepting function declarations as record declarations.
+ // In general, we cannot solve this problem. Consider:
+ // class A<int> B() {}
+ // which can be a function definition or a class definition when B() is a
+ // macro. If we find enough real-world cases where this is a problem, we
+ // can parse for the 'template' keyword in the beginning of the statement,
+ // and thus rule out the record production in case there is no template
+ // (this would still leave us with an ambiguity between template function
+ // and class declarations).
+ if (FormatTok->isOneOf(tok::colon, tok::less)) {
+ while (!eof()) {
+ if (FormatTok->is(tok::l_brace)) {
+ calculateBraceTypes(/*ExpectClassBody=*/true);
+ if (!tryToParseBracedList())
+ break;
}
+ if (FormatTok->Tok.is(tok::semi))
+ return;
+ nextToken();
}
}
if (FormatTok->Tok.is(tok::l_brace)) {
@@ -1495,12 +1681,9 @@ void UnwrappedLineParser::parseRecord() {
parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
/*MunchSemi=*/false);
}
- // We fall through to parsing a structural element afterwards, so
- // class A {} n, m;
- // will end up in one unwrapped line.
- // This does not apply for Java.
- if (Style.Language == FormatStyle::LK_Java)
- addUnwrappedLine();
+ // There is no addUnwrappedLine() here so that we fall through to parsing a
+ // structural element afterwards. Thus, in "class A {} n, m;",
+ // "} n, m;" will end up in one unwrapped line.
}
void UnwrappedLineParser::parseObjCProtocolList() {
@@ -1578,6 +1761,36 @@ void UnwrappedLineParser::parseObjCProtocol() {
parseObjCUntilAtEnd();
}
+void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
+ assert(FormatTok->isOneOf(Keywords.kw_import, tok::kw_export));
+ nextToken();
+
+ // Consume the "default" in "export default class/function".
+ if (FormatTok->is(tok::kw_default))
+ nextToken();
+
+ // Consume "function" and "default function", so that these get parsed as
+ // free-standing JS functions, i.e. do not require a trailing semicolon.
+ if (FormatTok->is(Keywords.kw_function)) {
+ nextToken();
+ return;
+ }
+
+ if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, tok::kw_enum,
+ Keywords.kw_var))
+ return; // Fall through to parsing the corresponding structure.
+
+ if (FormatTok->is(tok::l_brace)) {
+ FormatTok->BlockKind = BK_Block;
+ parseBracedList();
+ }
+
+ while (!eof() && FormatTok->isNot(tok::semi) &&
+ FormatTok->isNot(tok::l_brace)) {
+ nextToken();
+ }
+}
+
LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
StringRef Prefix = "") {
llvm::dbgs() << Prefix << "Line(" << Line.Level << ")"
@@ -1608,15 +1821,12 @@ void UnwrappedLineParser::addUnwrappedLine() {
if (CurrentLines == &Lines)
printDebugInfo(*Line);
});
- CurrentLines->push_back(*Line);
+ CurrentLines->push_back(std::move(*Line));
Line->Tokens.clear();
if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
- for (SmallVectorImpl<UnwrappedLine>::iterator
- I = PreprocessorDirectives.begin(),
- E = PreprocessorDirectives.end();
- I != E; ++I) {
- CurrentLines->push_back(*I);
- }
+ CurrentLines->append(
+ std::make_move_iterator(PreprocessorDirectives.begin()),
+ std::make_move_iterator(PreprocessorDirectives.end()));
PreprocessorDirectives.clear();
}
}
@@ -1634,14 +1844,12 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
I = CommentsBeforeNextToken.begin(),
E = CommentsBeforeNextToken.end();
I != E; ++I) {
- if (isOnNewLine(**I) && JustComments) {
+ if (isOnNewLine(**I) && JustComments)
addUnwrappedLine();
- }
pushToken(*I);
}
- if (NewlineBeforeNext && JustComments) {
+ if (NewlineBeforeNext && JustComments)
addUnwrappedLine();
- }
CommentsBeforeNextToken.clear();
}
@@ -1662,8 +1870,7 @@ void UnwrappedLineParser::readToken() {
(FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) {
// If there is an unfinished unwrapped line, we flush the preprocessor
// directives only after that unwrapped line was finished later.
- bool SwitchToPreprocessorLines =
- !Line->Tokens.empty() && CurrentLines == &Lines;
+ bool SwitchToPreprocessorLines = !Line->Tokens.empty();
ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
// Comments stored before the preprocessor directive need to be output
// before the preprocessor directive, at the same level as the
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
index 3218afe..c2fa029 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
@@ -65,8 +65,7 @@ public:
ArrayRef<FormatToken *> Tokens,
UnwrappedLineConsumer &Callback);
- /// Returns true in case of a structural error.
- bool parse();
+ void parse();
private:
void reset();
@@ -95,6 +94,7 @@ private:
void parseCaseLabel();
void parseSwitch();
void parseNamespace();
+ void parseNew();
void parseAccessSpecifier();
void parseEnum();
void parseJavaEnumBody();
@@ -103,6 +103,7 @@ private:
void parseObjCUntilAtEnd();
void parseObjCInterfaceOrImplementation();
void parseObjCProtocol();
+ void parseJavaScriptEs6ImportExport();
bool tryToParseLambda();
bool tryToParseLambdaIntroducer();
void tryToParseJSFunction();
@@ -112,7 +113,7 @@ private:
void readToken();
void flushComments(bool NewlineBeforeNext);
void pushToken(FormatToken *Tok);
- void calculateBraceTypes();
+ void calculateBraceTypes(bool ExpectClassBody = false);
// Marks a conditional compilation edge (for example, an '#if', '#ifdef',
// '#else' or merge conflict marker). If 'Unreachable' is true, assumes
@@ -156,10 +157,6 @@ private:
// whether we are in a compound statement or not.
std::vector<bool> DeclarationScopeStack;
- // Will be true if we encounter an error that leads to possibily incorrect
- // indentation levels.
- bool StructuralError;
-
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
index bf1207e..6539527 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
@@ -36,7 +36,9 @@ WhitespaceManager::Change::Change(
PreviousLinePostfix(PreviousLinePostfix),
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
ContinuesPPDirective(ContinuesPPDirective), IndentLevel(IndentLevel),
- Spaces(Spaces) {}
+ Spaces(Spaces), IsTrailingComment(false), TokenLength(0),
+ PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
+ StartOfBlockComment(nullptr), IndentationOffset(0) {}
void WhitespaceManager::reset() {
Changes.clear();
@@ -91,6 +93,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
+ alignConsecutiveAssignments();
alignTrailingComments();
alignEscapedNewlines();
generateChanges();
@@ -139,6 +142,96 @@ void WhitespaceManager::calculateLineBreakInformation() {
}
}
+// Walk through all of the changes and find sequences of "=" to align. To do
+// so, keep track of the lines and whether or not an "=" was found on align. If
+// a "=" is found on a line, extend the current sequence. If the current line
+// cannot be part of a sequence, e.g. because there is an empty line before it
+// or it contains non-assignments, finalize the previous sequence.
+void WhitespaceManager::alignConsecutiveAssignments() {
+ if (!Style.AlignConsecutiveAssignments)
+ return;
+
+ unsigned MinColumn = 0;
+ unsigned StartOfSequence = 0;
+ unsigned EndOfSequence = 0;
+ bool FoundAssignmentOnLine = false;
+ bool FoundLeftParenOnLine = false;
+ unsigned CurrentLine = 0;
+
+ auto AlignSequence = [&] {
+ alignConsecutiveAssignments(StartOfSequence, EndOfSequence, MinColumn);
+ MinColumn = 0;
+ StartOfSequence = 0;
+ EndOfSequence = 0;
+ };
+
+ for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
+ if (Changes[i].NewlinesBefore != 0) {
+ CurrentLine += Changes[i].NewlinesBefore;
+ if (StartOfSequence > 0 &&
+ (Changes[i].NewlinesBefore > 1 || !FoundAssignmentOnLine)) {
+ EndOfSequence = i;
+ AlignSequence();
+ }
+ FoundAssignmentOnLine = false;
+ FoundLeftParenOnLine = false;
+ }
+
+ if ((Changes[i].Kind == tok::equal &&
+ (FoundAssignmentOnLine || ((Changes[i].NewlinesBefore > 0 ||
+ Changes[i + 1].NewlinesBefore > 0)))) ||
+ (!FoundLeftParenOnLine && Changes[i].Kind == tok::r_paren)) {
+ if (StartOfSequence > 0)
+ AlignSequence();
+ } else if (Changes[i].Kind == tok::l_paren) {
+ FoundLeftParenOnLine = true;
+ if (!FoundAssignmentOnLine && StartOfSequence > 0)
+ AlignSequence();
+ } else if (!FoundAssignmentOnLine && !FoundLeftParenOnLine &&
+ Changes[i].Kind == tok::equal) {
+ FoundAssignmentOnLine = true;
+ EndOfSequence = i;
+ if (StartOfSequence == 0)
+ StartOfSequence = i;
+
+ unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ MinColumn = std::max(MinColumn, ChangeMinColumn);
+ }
+ }
+
+ if (StartOfSequence > 0) {
+ EndOfSequence = Changes.size();
+ AlignSequence();
+ }
+}
+
+void WhitespaceManager::alignConsecutiveAssignments(unsigned Start,
+ unsigned End,
+ unsigned Column) {
+ bool AlignedAssignment = false;
+ int PreviousShift = 0;
+ for (unsigned i = Start; i != End; ++i) {
+ int Shift = 0;
+ if (Changes[i].NewlinesBefore > 0)
+ AlignedAssignment = false;
+ if (!AlignedAssignment && Changes[i].Kind == tok::equal) {
+ Shift = Column - Changes[i].StartOfTokenColumn;
+ AlignedAssignment = true;
+ PreviousShift = Shift;
+ }
+ assert(Shift >= 0);
+ Changes[i].Spaces += Shift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ Changes[i].StartOfTokenColumn += Shift;
+ if (AlignedAssignment) {
+ Changes[i].StartOfTokenColumn += PreviousShift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += PreviousShift;
+ }
+ }
+}
+
void WhitespaceManager::alignTrailingComments() {
unsigned MinColumn = 0;
unsigned MaxColumn = UINT_MAX;
@@ -264,6 +357,11 @@ void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,
void WhitespaceManager::generateChanges() {
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
const Change &C = Changes[i];
+ if (i > 0) {
+ assert(Changes[i - 1].OriginalWhitespaceRange.getBegin() !=
+ C.OriginalWhitespaceRange.getBegin() &&
+ "Generating two replacements for the same location");
+ }
if (C.CreateReplacement) {
std::string ReplacementText = C.PreviousLinePostfix;
if (C.ContinuesPPDirective)
@@ -304,7 +402,7 @@ void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines,
unsigned Offset =
std::min<int>(EscapedNewlineColumn - 1, PreviousEndOfTokenColumn);
for (unsigned i = 0; i < Newlines; ++i) {
- Text.append(std::string(EscapedNewlineColumn - Offset - 1, ' '));
+ Text.append(EscapedNewlineColumn - Offset - 1, ' ');
Text.append(UseCRLF ? "\\\r\n" : "\\\n");
Offset = 0;
}
@@ -316,7 +414,7 @@ void WhitespaceManager::appendIndentText(std::string &Text,
unsigned WhitespaceStartColumn) {
switch (Style.UseTab) {
case FormatStyle::UT_Never:
- Text.append(std::string(Spaces, ' '));
+ Text.append(Spaces, ' ');
break;
case FormatStyle::UT_Always: {
unsigned FirstTabWidth =
@@ -326,8 +424,8 @@ void WhitespaceManager::appendIndentText(std::string &Text,
Spaces -= FirstTabWidth;
Text.append("\t");
}
- Text.append(std::string(Spaces / Style.TabWidth, '\t'));
- Text.append(std::string(Spaces % Style.TabWidth, ' '));
+ Text.append(Spaces / Style.TabWidth, '\t');
+ Text.append(Spaces % Style.TabWidth, ' ');
break;
}
case FormatStyle::UT_ForIndentation:
@@ -338,10 +436,10 @@ void WhitespaceManager::appendIndentText(std::string &Text,
if (Indentation > Spaces)
Indentation = Spaces;
unsigned Tabs = Indentation / Style.TabWidth;
- Text.append(std::string(Tabs, '\t'));
+ Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;
}
- Text.append(std::string(Spaces, ' '));
+ Text.append(Spaces, ' ');
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
index 28730d4..d973838 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
@@ -164,6 +164,15 @@ private:
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
void calculateLineBreakInformation();
+ /// \brief Align consecutive assignments over all \c Changes.
+ void alignConsecutiveAssignments();
+
+ /// \brief Align consecutive assignments from change \p Start to change \p End
+ /// at
+ /// the specified \p Column.
+ void alignConsecutiveAssignments(unsigned Start, unsigned End,
+ unsigned Column);
+
/// \brief Align trailing comments over all \c Changes.
void alignTrailingComments();
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
index f53c614..52776b6 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
@@ -21,7 +21,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "llvm/IR/Module.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
index 216ac6a..f6f1551 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
@@ -45,8 +45,10 @@ void ASTMergeAction::ExecuteAction() {
new ForwardingDiagnosticConsumer(
*CI.getDiagnostics().getClient()),
/*ShouldOwnClient=*/true));
- std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
- ASTFiles[I], Diags, CI.getFileSystemOpts(), false);
+ std::unique_ptr<ASTUnit> Unit =
+ ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerOperations(),
+ Diags, CI.getFileSystemOpts(), false);
+
if (!Unit)
continue;
@@ -57,6 +59,7 @@ void ASTMergeAction::ExecuteAction() {
/*MinimalImport=*/false);
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
+ CI.getASTConsumer().Initialize(CI.getASTContext());
for (auto *D : TU->decls()) {
// Don't re-import __va_list_tag, __builtin_va_list.
if (const auto *ND = dyn_cast<NamedDecl>(D))
@@ -64,7 +67,12 @@ void ASTMergeAction::ExecuteAction() {
if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list"))
continue;
- Importer.Import(D);
+ Decl *ToD = Importer.Import(D);
+
+ if (ToD) {
+ DeclGroupRef DGR(ToD);
+ CI.getASTConsumer().HandleTopLevelDecl(DGR);
+ }
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index a3998fa..57c97d0 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -120,11 +120,10 @@ static OnDiskDataMap &getOnDiskDataMap() {
static void cleanupOnDiskMapAtExit() {
// Use the mutex because there can be an alive thread destroying an ASTUnit.
llvm::MutexGuard Guard(getOnDiskMutex());
- OnDiskDataMap &M = getOnDiskDataMap();
- for (OnDiskDataMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ for (const auto &I : getOnDiskDataMap()) {
// We don't worry about freeing the memory associated with OnDiskDataMap.
// All we care about is erasing stale files.
- I->second->Cleanup();
+ I.second->Cleanup();
}
}
@@ -151,7 +150,7 @@ static void removeOnDiskEntry(const ASTUnit *AU) {
OnDiskDataMap::iterator I = M.find(AU);
if (I != M.end()) {
I->second->Cleanup();
- M.erase(AU);
+ M.erase(I);
}
}
@@ -164,8 +163,8 @@ static const std::string &getPreambleFile(const ASTUnit *AU) {
}
void OnDiskData::CleanTemporaryFiles() {
- for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
- llvm::sys::fs::remove(TemporaryFiles[I]);
+ for (StringRef File : TemporaryFiles)
+ llvm::sys::fs::remove(File);
TemporaryFiles.clear();
}
@@ -354,26 +353,25 @@ void ASTUnit::CacheCodeCompletionResults() {
// Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
-
- for (unsigned I = 0, N = Results.size(); I != N; ++I) {
- switch (Results[I].Kind) {
+ CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
+
+ for (Result &R : Results) {
+ switch (R.Kind) {
case Result::RK_Declaration: {
bool IsNestedNameSpecifier = false;
CachedCodeCompletionResult CachedResult;
- CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
- *CachedCompletionAllocator,
- CCTUInfo,
- IncludeBriefCommentsInCodeCompletion);
- CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
- Ctx->getLangOpts(),
- IsNestedNameSpecifier);
- CachedResult.Priority = Results[I].Priority;
- CachedResult.Kind = Results[I].CursorKind;
- CachedResult.Availability = Results[I].Availability;
+ CachedResult.Completion = R.CreateCodeCompletionString(
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
+ IncludeBriefCommentsInCodeCompletion);
+ CachedResult.ShowInContexts = getDeclShowContexts(
+ R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);
+ CachedResult.Priority = R.Priority;
+ CachedResult.Kind = R.CursorKind;
+ CachedResult.Availability = R.Availability;
// Keep track of the type of this completion in an ASTContext-agnostic
// way.
- QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
+ QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
if (UsageType.isNull()) {
CachedResult.TypeClass = STC_Void;
CachedResult.Type = 0;
@@ -398,8 +396,8 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedCompletionResults.push_back(CachedResult);
/// Handle nested-name-specifiers in C++.
- if (TheSema->Context.getLangOpts().CPlusPlus &&
- IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
+ if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&
+ !R.StartsNestedNameSpecifier) {
// The contexts in which a nested-name-specifier can appear in C++.
uint64_t NNSContexts
= (1LL << CodeCompletionContext::CCC_TopLevel)
@@ -415,8 +413,8 @@ void ASTUnit::CacheCodeCompletionResults() {
| (1LL << CodeCompletionContext::CCC_PotentiallyQualifiedName)
| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
- if (isa<NamespaceDecl>(Results[I].Declaration) ||
- isa<NamespaceAliasDecl>(Results[I].Declaration))
+ if (isa<NamespaceDecl>(R.Declaration) ||
+ isa<NamespaceAliasDecl>(R.Declaration))
NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
if (unsigned RemainingContexts
@@ -424,12 +422,10 @@ void ASTUnit::CacheCodeCompletionResults() {
// If there any contexts where this completion can be a
// nested-name-specifier but isn't already an option, create a
// nested-name-specifier completion.
- Results[I].StartsNestedNameSpecifier = true;
- CachedResult.Completion
- = Results[I].CreateCodeCompletionString(*TheSema,
- *CachedCompletionAllocator,
- CCTUInfo,
- IncludeBriefCommentsInCodeCompletion);
+ R.StartsNestedNameSpecifier = true;
+ CachedResult.Completion = R.CreateCodeCompletionString(
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
+ IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts = RemainingContexts;
CachedResult.Priority = CCP_NestedNameSpecifier;
CachedResult.TypeClass = STC_Void;
@@ -448,11 +444,9 @@ void ASTUnit::CacheCodeCompletionResults() {
case Result::RK_Macro: {
CachedCodeCompletionResult CachedResult;
- CachedResult.Completion
- = Results[I].CreateCodeCompletionString(*TheSema,
- *CachedCompletionAllocator,
- CCTUInfo,
- IncludeBriefCommentsInCodeCompletion);
+ CachedResult.Completion = R.CreateCodeCompletionString(
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
+ IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts
= (1LL << CodeCompletionContext::CCC_TopLevel)
| (1LL << CodeCompletionContext::CCC_ObjCInterface)
@@ -466,10 +460,10 @@ void ASTUnit::CacheCodeCompletionResults() {
| (1LL << CodeCompletionContext::CCC_PreprocessorExpression)
| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
| (1LL << CodeCompletionContext::CCC_OtherWithMacros);
-
- CachedResult.Priority = Results[I].Priority;
- CachedResult.Kind = Results[I].CursorKind;
- CachedResult.Availability = Results[I].Availability;
+
+ CachedResult.Priority = R.Priority;
+ CachedResult.Kind = R.CursorKind;
+ CachedResult.Availability = R.Availability;
CachedResult.TypeClass = STC_Void;
CachedResult.Type = 0;
CachedCompletionResults.push_back(CachedResult);
@@ -520,8 +514,8 @@ public:
return false;
}
- bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) override {
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
// If we've already initialized the target, don't do it again.
if (Target)
return false;
@@ -620,7 +614,7 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
// about. This effectively drops diagnostics from modules we're building.
// FIXME: In the long run, ee don't want to drop source managers from modules.
if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr)
- StoredDiags.push_back(StoredDiagnostic(Level, Info));
+ StoredDiags.emplace_back(Level, Info);
}
ASTMutationListener *ASTUnit::getASTMutationListener() {
@@ -655,7 +649,9 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
- const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ const std::string &Filename,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls,
ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics,
bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) {
@@ -689,8 +685,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
PreprocessorOptions *PPOpts = new PreprocessorOptions();
- for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I)
- PPOpts->addRemappedFile(RemappedFiles[I].first, RemappedFiles[I].second);
+ for (const auto &RemappedFile : RemappedFiles)
+ PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second);
// Gather Info for preprocessor construction later on.
@@ -712,15 +708,22 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
bool disableValid = false;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = true;
- AST->Reader = new ASTReader(PP, Context,
- /*isysroot=*/"",
- /*DisableValidation=*/disableValid,
- AllowPCHWithCompilerErrors);
+ AST->Reader = new ASTReader(PP, Context, *PCHContainerOps,
+ /*isysroot=*/"",
+ /*DisableValidation=*/disableValid,
+ AllowPCHWithCompilerErrors);
AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>(
*AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target,
Counter));
+ // Attach the AST reader to the AST context as an external AST
+ // source, so that declarations will be deserialized from the
+ // AST file as needed.
+ // We need the external source to be set up before we read the AST, because
+ // eagerly-deserialized declarations may use it.
+ Context.setExternalSource(AST->Reader);
+
switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,
SourceLocation(), ASTReader::ARR_None)) {
case ASTReader::Success:
@@ -740,11 +743,6 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
PP.setCounterValue(Counter);
- // Attach the AST reader to the AST context as an external AST
- // source, so that declarations will be deserialized from the
- // AST file as needed.
- Context.setExternalSource(AST->Reader);
-
// Create an AST consumer, even though it isn't used.
AST->Consumer.reset(new ASTConsumer);
@@ -853,8 +851,8 @@ public:
}
bool HandleTopLevelDecl(DeclGroupRef D) override {
- for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
- handleTopLevelDecl(*it);
+ for (Decl *TopLevelDecl : D)
+ handleTopLevelDecl(TopLevelDecl);
return true;
}
@@ -862,8 +860,8 @@ public:
void HandleInterestingDecl(DeclGroupRef) override {}
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
- for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
- handleTopLevelDecl(*it);
+ for (Decl *TopLevelDecl : D)
+ handleTopLevelDecl(TopLevelDecl);
}
ASTMutationListener *GetASTMutationListener() override {
@@ -921,19 +919,21 @@ class PrecompilePreambleConsumer : public PCHGenerator {
unsigned &Hash;
std::vector<Decl *> TopLevelDecls;
PrecompilePreambleAction *Action;
+ raw_ostream *Out;
public:
PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action,
const Preprocessor &PP, StringRef isysroot,
raw_ostream *Out)
- : PCHGenerator(PP, "", nullptr, isysroot, Out, /*AllowASTWithErrors=*/true),
- Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) {
+ : PCHGenerator(PP, "", nullptr, isysroot, std::make_shared<PCHBuffer>(),
+ /*AllowASTWithErrors=*/true),
+ Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action),
+ Out(Out) {
Hash = 0;
}
- bool HandleTopLevelDecl(DeclGroupRef D) override {
- for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
- Decl *D = *it;
+ bool HandleTopLevelDecl(DeclGroupRef DG) override {
+ for (Decl *D : DG) {
// FIXME: Currently ObjC method declarations are incorrectly being
// reported as top-level declarations, even though their DeclContext
// is the containing ObjC @interface/@implementation. This is a
@@ -949,12 +949,19 @@ public:
void HandleTranslationUnit(ASTContext &Ctx) override {
PCHGenerator::HandleTranslationUnit(Ctx);
if (hasEmittedPCH()) {
+ // Write the generated bitstream to "Out".
+ *Out << getPCH();
+ // Make sure it hits disk now.
+ Out->flush();
+ // Free the buffer.
+ llvm::SmallVector<char, 0> Empty;
+ getPCH() = std::move(Empty);
+
// Translate the top-level declarations we captured during
// parsing into declaration IDs in the precompiled
// preamble. This will allow us to deserialize those top-level
// declarations when requested.
- for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I) {
- Decl *D = TopLevelDecls[I];
+ for (Decl *D : TopLevelDecls) {
// Invalid top-level decls may not have been serialized.
if (D->isInvalidDecl())
continue;
@@ -973,9 +980,9 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
- OutputFile, OS))
+ raw_ostream *OS = GeneratePCHAction::ComputeASTConsumerArguments(
+ CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
@@ -1009,10 +1016,10 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
// been careful to make sure that the source manager's state
// before and after are identical, so that we can reuse the source
// location itself.
- for (unsigned I = 0, N = StoredDiagnostics.size(); I < N; ++I) {
- if (StoredDiagnostics[I].getLocation().isValid()) {
- FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SM);
- StoredDiagnostics[I].setLocation(Loc);
+ for (StoredDiagnostic &SD : StoredDiagnostics) {
+ if (SD.getLocation().isValid()) {
+ FullSourceLoc Loc(SD.getLocation(), SM);
+ SD.setLocation(Loc);
}
}
}
@@ -1022,14 +1029,16 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
///
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
-bool ASTUnit::Parse(std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) {
+bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) {
SavedMainFileBuffer.reset();
if (!Invocation)
return true;
// Create the compiler instance to use for building the AST.
- std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ std::unique_ptr<CompilerInstance> Clang(
+ new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1300,14 +1309,10 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
if (OutDiag.Filename.empty())
return OutDiag;
OutDiag.LocOffset = SM.getFileOffset(FileLoc);
- for (StoredDiagnostic::range_iterator
- I = InDiag.range_begin(), E = InDiag.range_end(); I != E; ++I) {
- OutDiag.Ranges.push_back(makeStandaloneRange(*I, SM, LangOpts));
- }
- for (StoredDiagnostic::fixit_iterator I = InDiag.fixit_begin(),
- E = InDiag.fixit_end();
- I != E; ++I)
- OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, *I));
+ for (const CharSourceRange &Range : InDiag.getRanges())
+ OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
+ for (const FixItHint &FixIt : InDiag.getFixIts())
+ OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
return OutDiag;
}
@@ -1334,6 +1339,7 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
/// Otherwise, returns a NULL pointer.
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild,
unsigned MaxLines) {
@@ -1498,7 +1504,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
// Create the compiler instance to use for building the precompiled preamble.
- std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ std::unique_ptr<CompilerInstance> Clang(
+ new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1634,11 +1641,10 @@ void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
std::vector<Decl *> Resolved;
Resolved.reserve(TopLevelDeclsInPreamble.size());
ExternalASTSource &Source = *getASTContext().getExternalSource();
- for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
+ for (serialization::DeclID TopLevelDecl : TopLevelDeclsInPreamble) {
// Resolve the declaration ID to an actual declaration, possibly
// deserializing the declaration in the process.
- Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
- if (D)
+ if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
Resolved.push_back(D);
}
TopLevelDeclsInPreamble.clear();
@@ -1714,12 +1720,13 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI,
}
ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
- CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- ASTFrontendAction *Action, ASTUnit *Unit, bool Persistent,
- StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics,
- bool PrecompilePreamble, bool CacheCodeCompletionResults,
- bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile,
- std::unique_ptr<ASTUnit> *ErrAST) {
+ CompilerInvocation *CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action,
+ ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
+ bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
+ bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
+ bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {
assert(CI && "A CompilerInvocation is required");
std::unique_ptr<ASTUnit> OwnAST;
@@ -1758,7 +1765,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
// Create the compiler instance to use for building the AST.
- std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ std::unique_ptr<CompilerInstance> Clang(
+ new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1853,7 +1861,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
return AST;
}
-bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
+bool ASTUnit::LoadFromCompilerInvocation(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ bool PrecompilePreamble) {
if (!Invocation)
return true;
@@ -1865,7 +1875,8 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (PrecompilePreamble) {
PreambleRebuildCounter = 2;
- OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
+ OverrideMainBuffer =
+ getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
}
SimpleTimer ParsingTimer(WantTiming);
@@ -1875,12 +1886,14 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
MemBufferCleanup(OverrideMainBuffer.get());
- return Parse(std::move(OverrideMainBuffer));
+ return Parse(PCHContainerOps, std::move(OverrideMainBuffer));
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
- CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
+ CompilerInvocation *CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls,
+ bool CaptureDiagnostics, bool PrecompilePreamble,
TranslationUnitKind TUKind, bool CacheCodeCompletionResults,
bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) {
// Create the AST unit.
@@ -1909,13 +1922,14 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
DiagCleanup(Diags.get());
- if (AST->LoadFromCompilerInvocation(PrecompilePreamble))
+ if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble))
return nullptr;
return AST;
}
ASTUnit *ASTUnit::LoadFromCommandLine(
const char **ArgBegin, const char **ArgEnd,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
bool OnlyLocalDecls, bool CaptureDiagnostics,
ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
@@ -1943,9 +1957,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
}
// Override any files that need remapping
- for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I) {
- CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
- RemappedFiles[I].second);
+ for (const auto &RemappedFile : RemappedFiles) {
+ CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
+ RemappedFile.second);
}
PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
@@ -1987,7 +2001,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
- if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) {
+ if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit.
if (ErrAST) {
@@ -2000,7 +2014,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
return AST.release();
}
-bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
+bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ ArrayRef<RemappedFile> RemappedFiles) {
if (!Invocation)
return true;
@@ -2015,17 +2030,18 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
delete RB.second;
Invocation->getPreprocessorOpts().clearRemappedFiles();
- for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I) {
- Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
- RemappedFiles[I].second);
+ for (const auto &RemappedFile : RemappedFiles) {
+ Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
+ RemappedFile.second);
}
// If we have a preamble file lying around, or if we might try to
// build a precompiled preamble, do so now.
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
- OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
-
+ OverrideMainBuffer =
+ getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
+
// Clear out the diagnostics state.
getDiagnostics().Reset();
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
@@ -2033,7 +2049,7 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
getDiagnostics().setNumWarnings(NumWarningsInPreamble);
// Parse the sources
- bool Result = Parse(std::move(OverrideMainBuffer));
+ bool Result = Parse(PCHContainerOps, std::move(OverrideMainBuffer));
// If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache.
@@ -2285,18 +2301,15 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
AllResults.size());
}
-
-
-void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
- ArrayRef<RemappedFile> RemappedFiles,
- bool IncludeMacros,
- bool IncludeCodePatterns,
- bool IncludeBriefComments,
- CodeCompleteConsumer &Consumer,
- DiagnosticsEngine &Diag, LangOptions &LangOpts,
- SourceManager &SourceMgr, FileManager &FileMgr,
- SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
- SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
+void ASTUnit::CodeComplete(
+ StringRef File, unsigned Line, unsigned Column,
+ ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
+ bool IncludeCodePatterns, bool IncludeBriefComments,
+ CodeCompleteConsumer &Consumer,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
+ FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
if (!Invocation)
return;
@@ -2330,7 +2343,8 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
LangOpts.SpellChecking = false;
CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;
- std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ std::unique_ptr<CompilerInstance> Clang(
+ new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -2375,10 +2389,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// Remap files.
PreprocessorOpts.clearRemappedFiles();
PreprocessorOpts.RetainRemappedFileBuffers = true;
- for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I) {
- PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
- RemappedFiles[I].second);
- OwnedBuffers.push_back(RemappedFiles[I].second);
+ for (const auto &RemappedFile : RemappedFiles) {
+ PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);
+ OwnedBuffers.push_back(RemappedFile.second);
}
// Use the code completion consumer we were given, but adding any cached
@@ -2402,7 +2415,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) {
if (CompleteFileID == MainID && Line > 1)
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
- *CCInvocation, false, Line - 1);
+ PCHContainerOps, *CCInvocation, false, Line - 1);
}
}
}
@@ -2446,7 +2459,7 @@ bool ASTUnit::Save(StringRef File) {
TempPath = File;
TempPath += "-%%%%%%%%";
int fd;
- if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath))
+ if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
return true;
// FIXME: Can we somehow regenerate the stat cache here, or do we need to
@@ -2460,8 +2473,8 @@ bool ASTUnit::Save(StringRef File) {
return true;
}
- if (llvm::sys::fs::rename(TempPath.str(), File)) {
- llvm::sys::fs::remove(TempPath.str());
+ if (llvm::sys::fs::rename(TempPath, File)) {
+ llvm::sys::fs::remove(TempPath);
return true;
}
@@ -2509,9 +2522,8 @@ void ASTUnit::TranslateStoredDiagnostics(
SmallVector<StoredDiagnostic, 4> Result;
Result.reserve(Diags.size());
- for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
+ for (const StandaloneDiagnostic &SD : Diags) {
// Rebuild the StoredDiagnostic.
- const StandaloneDiagnostic &SD = Diags[I];
if (SD.Filename.empty())
continue;
const FileEntry *FE = FileMgr.getFile(SD.Filename);
@@ -2526,23 +2538,20 @@ void ASTUnit::TranslateStoredDiagnostics(
SmallVector<CharSourceRange, 4> Ranges;
Ranges.reserve(SD.Ranges.size());
- for (std::vector<std::pair<unsigned, unsigned> >::const_iterator
- I = SD.Ranges.begin(), E = SD.Ranges.end(); I != E; ++I) {
- SourceLocation BL = FileLoc.getLocWithOffset((*I).first);
- SourceLocation EL = FileLoc.getLocWithOffset((*I).second);
+ for (const auto &Range : SD.Ranges) {
+ SourceLocation BL = FileLoc.getLocWithOffset(Range.first);
+ SourceLocation EL = FileLoc.getLocWithOffset(Range.second);
Ranges.push_back(CharSourceRange::getCharRange(BL, EL));
}
SmallVector<FixItHint, 2> FixIts;
FixIts.reserve(SD.FixIts.size());
- for (std::vector<StandaloneFixIt>::const_iterator
- I = SD.FixIts.begin(), E = SD.FixIts.end();
- I != E; ++I) {
+ for (const StandaloneFixIt &FixIt : SD.FixIts) {
FixIts.push_back(FixItHint());
FixItHint &FH = FixIts.back();
- FH.CodeToInsert = I->CodeToInsert;
- SourceLocation BL = FileLoc.getLocWithOffset(I->RemoveRange.first);
- SourceLocation EL = FileLoc.getLocWithOffset(I->RemoveRange.second);
+ FH.CodeToInsert = FixIt.CodeToInsert;
+ SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);
+ SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);
FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
}
@@ -2736,7 +2745,7 @@ SourceLocation ASTUnit::getStartOfMainFileID() {
return SourceMgr->getLocForStartOfFile(FID);
}
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+llvm::iterator_range<PreprocessingRecord::iterator>
ASTUnit::getLocalPreprocessingEntities() const {
if (isMainFileAST()) {
serialization::ModuleFile &
@@ -2745,20 +2754,18 @@ ASTUnit::getLocalPreprocessingEntities() const {
}
if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
- return std::make_pair(PPRec->local_begin(), PPRec->local_end());
+ return llvm::make_range(PPRec->local_begin(), PPRec->local_end());
- return std::make_pair(PreprocessingRecord::iterator(),
- PreprocessingRecord::iterator());
+ return llvm::make_range(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
}
bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
if (isMainFileAST()) {
serialization::ModuleFile &
Mod = Reader->getModuleManager().getPrimaryModule();
- ASTReader::ModuleDeclIterator MDI, MDE;
- std::tie(MDI, MDE) = Reader->getModuleFileLevelDecls(Mod);
- for (; MDI != MDE; ++MDI) {
- if (!Fn(context, *MDI))
+ for (const Decl *D : Reader->getModuleFileLevelDecls(Mod)) {
+ if (!Fn(context, D))
return false;
}
@@ -2821,11 +2828,8 @@ void ASTUnit::PreambleData::countLines() const {
if (empty())
return;
- for (std::vector<char>::const_iterator
- I = Buffer.begin(), E = Buffer.end(); I != E; ++I) {
- if (*I == '\n')
- ++NumLines;
- }
+ NumLines = std::count(Buffer.begin(), Buffer.end(), '\n');
+
if (Buffer.back() != '\n')
++NumLines;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
index d909d52..7d2a09c 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
@@ -183,7 +183,7 @@ class PTHWriter {
typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
IDMap IM;
- llvm::raw_fd_ostream& Out;
+ raw_pwrite_stream &Out;
Preprocessor& PP;
uint32_t idcount;
PTHMap PM;
@@ -236,8 +236,8 @@ class PTHWriter {
Offset EmitCachedSpellings();
public:
- PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
- : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
+ PTHWriter(raw_pwrite_stream &out, Preprocessor &pp)
+ : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
PTHMap &getPM() { return PM; }
void GeneratePTH(const std::string &MainFile);
@@ -468,6 +468,16 @@ Offset PTHWriter::EmitCachedSpellings() {
return SpellingsOff;
}
+static uint32_t swap32le(uint32_t X) {
+ return llvm::support::endian::byte_swap<uint32_t, llvm::support::little>(X);
+}
+
+static void pwrite32le(raw_pwrite_stream &OS, uint32_t Val, uint64_t &Off) {
+ uint32_t LEVal = swap32le(Val);
+ OS.pwrite(reinterpret_cast<const char *>(&LEVal), 4, Off);
+ Off += 4;
+}
+
void PTHWriter::GeneratePTH(const std::string &MainFile) {
// Generate the prologue.
Out << "cfe-pth" << '\0';
@@ -520,11 +530,11 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) {
Offset FileTableOff = EmitFileTable();
// Finally, write the prologue.
- Out.seek(PrologueOffset);
- Emit32(IdTableOff.first);
- Emit32(IdTableOff.second);
- Emit32(FileTableOff);
- Emit32(SpellingOff);
+ uint64_t Off = PrologueOffset;
+ pwrite32le(Out, IdTableOff.first, Off);
+ pwrite32le(Out, IdTableOff.second, Off);
+ pwrite32le(Out, FileTableOff, Off);
+ pwrite32le(Out, SpellingOff, Off);
}
namespace {
@@ -537,7 +547,7 @@ class StatListener : public FileSystemStatCache {
PTHMap &PM;
public:
StatListener(PTHMap &pm) : PM(pm) {}
- ~StatListener() {}
+ ~StatListener() override {}
LookupResult getStat(const char *Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
@@ -559,8 +569,7 @@ public:
};
} // end anonymous namespace
-
-void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
+void clang::CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS) {
// Get the name of the main file.
const SourceManager &SrcMgr = PP.getSourceManager();
const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
index cb260b4..be30d43 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -27,7 +27,7 @@ using namespace clang;
namespace {
class ChainedIncludesSource : public ExternalSemaSource {
public:
- virtual ~ChainedIncludesSource();
+ ~ChainedIncludesSource() override;
ExternalSemaSource &getFinalReader() const { return *FinalReader; }
@@ -43,6 +43,7 @@ protected:
Selector GetExternalSelector(uint32_t ID) override;
uint32_t GetNumExternalSelectors() override;
Stmt *GetExternalDeclStmt(uint64_t Offset) override;
+ CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
@@ -79,8 +80,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
std::unique_ptr<ASTReader> Reader;
- Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"",
- /*DisableValidation=*/true));
+ Reader.reset(new ASTReader(PP, CI.getASTContext(),
+ *CI.getPCHContainerOperations(),
+ /*isysroot=*/"", /*DisableValidation=*/true));
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
StringRef sr(bufNames[ti]);
Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
@@ -144,7 +146,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
- std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ std::unique_ptr<CompilerInstance> Clang(
+ new CompilerInstance(CI.getPCHContainerOperations()));
Clang->setInvocation(CInvok.release());
Clang->setDiagnostics(Diags.get());
Clang->setTarget(TargetInfo::CreateTargetInfo(
@@ -156,11 +159,9 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
&Clang->getPreprocessor());
Clang->createASTContext();
- SmallVector<char, 256> serialAST;
- llvm::raw_svector_ostream OS(serialAST);
- auto consumer =
- llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr,
- /*isysroot=*/"", &OS);
+ auto Buffer = std::make_shared<PCHBuffer>();
+ auto consumer = llvm::make_unique<PCHGenerator>(
+ Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
@@ -197,7 +198,11 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
ParseAST(Clang->getSema());
Clang->getDiagnosticClient().EndSourceFile();
- SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
+ assert(Buffer->IsComplete && "serialization did not complete");
+ auto &serialAST = Buffer->Data;
+ SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(serialAST.data(), serialAST.size())));
+ serialAST.clear();
source->CIs.push_back(Clang.release());
}
@@ -232,6 +237,10 @@ CXXBaseSpecifier *
ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
}
+CXXCtorInitializer **
+ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ return getFinalReader().GetExternalCXXCtorInitializers(Offset);
+}
bool
ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
index 93a34b7..ff041a8 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -51,12 +51,13 @@
using namespace clang;
-CompilerInstance::CompilerInstance(bool BuildingModule)
- : ModuleLoader(BuildingModule),
- Invocation(new CompilerInvocation()), ModuleManager(nullptr),
- BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false),
- ModuleBuildFailed(false) {
-}
+CompilerInstance::CompilerInstance(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ bool BuildingModule)
+ : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()),
+ ModuleManager(nullptr), ThePCHContainerOperations(PCHContainerOps),
+ BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false),
+ ModuleBuildFailed(false) {}
CompilerInstance::~CompilerInstance() {
assert(OutputFiles.empty() && "Still output files in flight?");
@@ -321,7 +322,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP->getFileManager(), PPOpts);
// Predefine macros and configure the preprocessor.
- InitializePreprocessor(*PP, PPOpts, getFrontendOpts());
+ InitializePreprocessor(*PP, PPOpts, *getPCHContainerOperations(),
+ getFrontendOpts());
// Initialize the header search object.
ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
@@ -329,14 +331,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
- // Set up the module path, including the hash for the
- // module-creation options.
- SmallString<256> SpecificModuleCache(
- getHeaderSearchOpts().ModuleCachePath);
- if (!getHeaderSearchOpts().DisableModuleHash)
- llvm::sys::path::append(SpecificModuleCache,
- getInvocation().getModuleHash());
- PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache);
+ if (PP->getLangOpts().Modules)
+ PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
// Handle generating dependencies, if requested.
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
@@ -371,14 +367,17 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"",
/*ShowDepth=*/true, /*MSStyle=*/true);
}
+}
- // Load all explictly-specified module map files.
- for (const auto &Filename : getFrontendOpts().ModuleMapFiles) {
- if (auto *File = getFileManager().getFile(Filename))
- PP->getHeaderSearchInfo().loadModuleMapFile(File, /*IsSystem*/false);
- else
- getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
- }
+std::string CompilerInstance::getSpecificModuleCachePath() {
+ // Set up the module path, including the hash for the
+ // module-creation options.
+ SmallString<256> SpecificModuleCache(
+ getHeaderSearchOpts().ModuleCachePath);
+ if (!getHeaderSearchOpts().DisableModuleHash)
+ llvm::sys::path::append(SpecificModuleCache,
+ getInvocation().getModuleHash());
+ return SpecificModuleCache.str();
}
// ASTContext
@@ -396,32 +395,32 @@ void CompilerInstance::createASTContext() {
void CompilerInstance::createPCHExternalASTSource(
StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,
void *DeserializationListener, bool OwnDeserializationListener) {
- IntrusiveRefCntPtr<ExternalASTSource> Source;
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
- Source = createPCHExternalASTSource(
+ ModuleManager = createPCHExternalASTSource(
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
- DeserializationListener, OwnDeserializationListener, Preamble,
+ *getPCHContainerOperations(), DeserializationListener,
+ OwnDeserializationListener, Preamble,
getFrontendOpts().UseGlobalModuleIndex);
- ModuleManager = static_cast<ASTReader*>(Source.get());
- getASTContext().setExternalSource(Source);
}
-ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
- StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
+IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
+ StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
+ const PCHContainerOperations &PCHContainerOps,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex) {
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
- std::unique_ptr<ASTReader> Reader;
- Reader.reset(new ASTReader(PP, Context,
- Sysroot.empty() ? "" : Sysroot.c_str(),
- DisablePCHValidation,
- AllowPCHWithCompilerErrors,
- /*AllowConfigurationMismatch*/false,
- HSOpts.ModulesValidateSystemHeaders,
- UseGlobalModuleIndex));
+ IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
+ PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.data(),
+ DisablePCHValidation, AllowPCHWithCompilerErrors,
+ /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders,
+ UseGlobalModuleIndex));
+
+ // We need the external source to be set up before we read the AST, because
+ // eagerly-deserialized declarations may use it.
+ Context.setExternalSource(Reader.get());
Reader->setDeserializationListener(
static_cast<ASTDeserializationListener *>(DeserializationListener),
@@ -435,7 +434,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
// Set the predefines buffer as suggested by the PCH reader. Typically, the
// predefines buffer will be empty.
PP.setPredefines(Reader->getSuggestedPredefines());
- return Reader.release();
+ return Reader;
case ASTReader::Failure:
// Unrecoverable failure: don't even try to process the input file.
@@ -450,6 +449,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
break;
}
+ Context.setExternalSource(nullptr);
return nullptr;
}
@@ -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,
@@ -522,42 +524,43 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
// Output Files
-void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
+void CompilerInstance::addOutputFile(OutputFile &&OutFile) {
assert(OutFile.OS && "Attempt to add empty stream to output list!");
- OutputFiles.push_back(OutFile);
+ OutputFiles.push_back(std::move(OutFile));
}
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
- for (std::list<OutputFile>::iterator
- it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
- delete it->OS;
- if (!it->TempFilename.empty()) {
+ for (OutputFile &OF : OutputFiles) {
+ // Manually close the stream before we rename it.
+ OF.OS.reset();
+
+ if (!OF.TempFilename.empty()) {
if (EraseFiles) {
- llvm::sys::fs::remove(it->TempFilename);
+ llvm::sys::fs::remove(OF.TempFilename);
} else {
- SmallString<128> NewOutFile(it->Filename);
+ SmallString<128> NewOutFile(OF.Filename);
// If '-working-directory' was passed, the output filename should be
// relative to that.
FileMgr->FixupRelativePath(NewOutFile);
if (std::error_code ec =
- llvm::sys::fs::rename(it->TempFilename, NewOutFile.str())) {
+ llvm::sys::fs::rename(OF.TempFilename, NewOutFile)) {
getDiagnostics().Report(diag::err_unable_to_rename_temp)
- << it->TempFilename << it->Filename << ec.message();
+ << OF.TempFilename << OF.Filename << ec.message();
- llvm::sys::fs::remove(it->TempFilename);
+ llvm::sys::fs::remove(OF.TempFilename);
}
}
- } else if (!it->Filename.empty() && EraseFiles)
- llvm::sys::fs::remove(it->Filename);
+ } else if (!OF.Filename.empty() && EraseFiles)
+ llvm::sys::fs::remove(OF.Filename);
}
OutputFiles.clear();
+ NonSeekStream.reset();
}
-llvm::raw_fd_ostream *
-CompilerInstance::createDefaultOutputFile(bool Binary,
- StringRef InFile,
+raw_pwrite_stream *
+CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
StringRef Extension) {
return createOutputFile(getFrontendOpts().OutputFile, Binary,
/*RemoveFileOnSignal=*/true, InFile, Extension,
@@ -565,21 +568,20 @@ CompilerInstance::createDefaultOutputFile(bool Binary,
}
llvm::raw_null_ostream *CompilerInstance::createNullOutputFile() {
- llvm::raw_null_ostream *OS = new llvm::raw_null_ostream();
- addOutputFile(OutputFile("", "", OS));
- return OS;
+ auto OS = llvm::make_unique<llvm::raw_null_ostream>();
+ llvm::raw_null_ostream *Ret = OS.get();
+ addOutputFile(OutputFile("", "", std::move(OS)));
+ return Ret;
}
-llvm::raw_fd_ostream *
-CompilerInstance::createOutputFile(StringRef OutputPath,
- bool Binary, bool RemoveFileOnSignal,
- StringRef InFile,
- StringRef Extension,
- bool UseTemporary,
+raw_pwrite_stream *
+CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
+ bool RemoveFileOnSignal, StringRef InFile,
+ StringRef Extension, bool UseTemporary,
bool CreateMissingDirectories) {
std::string OutputPathName, TempPathName;
std::error_code EC;
- llvm::raw_fd_ostream *OS = createOutputFile(
+ std::unique_ptr<raw_pwrite_stream> OS = createOutputFile(
OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,
UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);
if (!OS) {
@@ -588,15 +590,16 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
return nullptr;
}
+ raw_pwrite_stream *Ret = OS.get();
// Add the output file -- but don't try to remove "-", since this means we are
// using stdin.
addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
- TempPathName, OS));
+ TempPathName, std::move(OS)));
- return OS;
+ return Ret;
}
-llvm::raw_fd_ostream *CompilerInstance::createOutputFile(
+std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
StringRef OutputPath, std::error_code &Error, bool Binary,
bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,
bool UseTemporary, bool CreateMissingDirectories,
@@ -646,14 +649,14 @@ llvm::raw_fd_ostream *CompilerInstance::createOutputFile(
TempPath += "-%%%%%%%%";
int fd;
std::error_code EC =
- llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath);
+ llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
if (CreateMissingDirectories &&
EC == llvm::errc::no_such_file_or_directory) {
StringRef Parent = llvm::sys::path::parent_path(OutputPath);
EC = llvm::sys::fs::create_directories(Parent);
if (!EC) {
- EC = llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath);
+ EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
}
}
@@ -684,7 +687,13 @@ llvm::raw_fd_ostream *CompilerInstance::createOutputFile(
if (TempPathName)
*TempPathName = TempFile;
- return OS.release();
+ if (!Binary || OS->supportsSeeking())
+ return std::move(OS);
+
+ auto B = llvm::make_unique<llvm::buffer_ostream>(*OS);
+ assert(!NonSeekStream);
+ NonSeekStream = std::move(OS);
+ return std::move(B);
}
// Initialization Utilities
@@ -915,7 +924,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
// Construct a compiler instance that will be used to actually create the
// module.
- CompilerInstance Instance(/*BuildingModule=*/true);
+ CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
+ /*BuildingModule=*/true);
Instance.setInvocation(&*Invocation);
Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
@@ -943,19 +953,20 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
if (const FileEntry *ModuleMapFile =
ModMap.getContainingModuleMapFile(Module)) {
// Use the module map where this module resides.
- FrontendOpts.Inputs.push_back(
- FrontendInputFile(ModuleMapFile->getName(), IK));
+ FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK);
} else {
+ SmallString<128> FakeModuleMapFile(Module->Directory->getName());
+ llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
+ FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK);
+
llvm::raw_string_ostream OS(InferredModuleMapContent);
Module->print(OS);
OS.flush();
- FrontendOpts.Inputs.push_back(
- FrontendInputFile("__inferred_module.map", IK));
std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
ModuleMapFile = Instance.getFileManager().getVirtualFile(
- "__inferred_module.map", InferredModuleMapContent.size(), 0);
+ FakeModuleMapFile, InferredModuleMapContent.size(), 0);
SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));
}
@@ -1031,9 +1042,19 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
case llvm::LockFileManager::LFS_Shared:
// Someone else is responsible for building the module. Wait for them to
// finish.
- if (Locked.waitForUnlock() == llvm::LockFileManager::Res_OwnerDied)
+ switch (Locked.waitForUnlock()) {
+ case llvm::LockFileManager::Res_Success:
+ ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate;
+ break;
+ case llvm::LockFileManager::Res_OwnerDied:
continue; // try again to get the lock.
- ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate;
+ case llvm::LockFileManager::Res_Timeout:
+ Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout)
+ << Module->Name;
+ // Clear the lock file so that future invokations can make progress.
+ Locked.unsafeRemoveLockFile();
+ return false;
+ }
break;
}
@@ -1071,79 +1092,51 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
// not have changed.
if (!Id->hadMacroDefinition())
return;
+ auto *LatestLocalMD = PP.getLocalMacroDirectiveHistory(Id);
- // If this identifier does not currently have a macro definition,
- // check whether it had one on the command line.
- if (!Id->hasMacroDefinition()) {
- MacroDirective::DefInfo LatestDef =
- PP.getMacroDirectiveHistory(Id)->getDefinition();
- for (MacroDirective::DefInfo Def = LatestDef; Def;
- Def = Def.getPreviousDefinition()) {
- FileID FID = SourceMgr.getFileID(Def.getLocation());
- if (FID.isInvalid())
- continue;
-
- // We only care about the predefines buffer.
- if (FID != PP.getPredefinesFileID())
- continue;
-
- // This macro was defined on the command line, then #undef'd later.
- // Complain.
- PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
- << true << ConfigMacro << Mod->getFullModuleName();
- if (LatestDef.isUndefined())
- PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
- << true;
- return;
- }
-
- // Okay: no definition in the predefines buffer.
- return;
- }
-
- // This identifier has a macro definition. Check whether we had a definition
- // on the command line.
- MacroDirective::DefInfo LatestDef =
- PP.getMacroDirectiveHistory(Id)->getDefinition();
- MacroDirective::DefInfo PredefinedDef;
- for (MacroDirective::DefInfo Def = LatestDef; Def;
- Def = Def.getPreviousDefinition()) {
- FileID FID = SourceMgr.getFileID(Def.getLocation());
- if (FID.isInvalid())
- continue;
-
+ // Find the macro definition from the command line.
+ MacroInfo *CmdLineDefinition = nullptr;
+ for (auto *MD = LatestLocalMD; MD; MD = MD->getPrevious()) {
// We only care about the predefines buffer.
- if (FID != PP.getPredefinesFileID())
+ FileID FID = SourceMgr.getFileID(MD->getLocation());
+ if (FID.isInvalid() || FID != PP.getPredefinesFileID())
continue;
-
- PredefinedDef = Def;
+ if (auto *DMD = dyn_cast<DefMacroDirective>(MD))
+ CmdLineDefinition = DMD->getMacroInfo();
break;
}
- // If there was no definition for this macro in the predefines buffer,
- // complain.
- if (!PredefinedDef ||
- (!PredefinedDef.getLocation().isValid() &&
- PredefinedDef.getUndefLocation().isValid())) {
+ auto *CurrentDefinition = PP.getMacroInfo(Id);
+ if (CurrentDefinition == CmdLineDefinition) {
+ // Macro matches. Nothing to do.
+ } else if (!CurrentDefinition) {
+ // This macro was defined on the command line, then #undef'd later.
+ // Complain.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << true << ConfigMacro << Mod->getFullModuleName();
+ auto LatestDef = LatestLocalMD->getDefinition();
+ assert(LatestDef.isUndefined() &&
+ "predefined macro went away with no #undef?");
+ PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
+ << true;
+ return;
+ } else if (!CmdLineDefinition) {
+ // There was no definition for this macro in the predefines buffer,
+ // but there was a local definition. Complain.
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
<< false << ConfigMacro << Mod->getFullModuleName();
- PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
+ PP.Diag(CurrentDefinition->getDefinitionLoc(),
+ diag::note_module_def_undef_here)
+ << false;
+ } else if (!CurrentDefinition->isIdenticalTo(*CmdLineDefinition, PP,
+ /*Syntactically=*/true)) {
+ // The macro definitions differ.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << false << ConfigMacro << Mod->getFullModuleName();
+ PP.Diag(CurrentDefinition->getDefinitionLoc(),
+ diag::note_module_def_undef_here)
<< false;
- return;
}
-
- // If the current macro definition is the same as the predefined macro
- // definition, it's okay.
- if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() ||
- LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP,
- /*Syntactically=*/true))
- return;
-
- // The macro definitions differ.
- PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
- << false << ConfigMacro << Mod->getFullModuleName();
- PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
- << false;
}
/// \brief Write a new timestamp file with the given path.
@@ -1186,8 +1179,7 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
std::error_code EC;
SmallString<128> ModuleCachePathNative;
llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative);
- for (llvm::sys::fs::directory_iterator
- Dir(ModuleCachePathNative.str(), EC), DirEnd;
+ for (llvm::sys::fs::directory_iterator Dir(ModuleCachePathNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// If we don't have a directory, there's nothing to look into.
if (!llvm::sys::fs::is_directory(Dir->path()))
@@ -1235,9 +1227,10 @@ void CompilerInstance::createModuleManager() {
if (!hasASTContext())
createASTContext();
- // If we're not recursively building a module, check whether we
- // need to prune the module cache.
- if (getSourceManager().getModuleBuildStack().empty() &&
+ // If we're implicitly building modules but not currently recursively
+ // building a module, check whether we need to prune the module cache.
+ if (getLangOpts().ImplicitModules &&
+ getSourceManager().getModuleBuildStack().empty() &&
getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
pruneModuleCache(getHeaderSearchOpts());
@@ -1246,13 +1239,18 @@ void CompilerInstance::createModuleManager() {
HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
std::string Sysroot = HSOpts.Sysroot;
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
- ModuleManager = new ASTReader(getPreprocessor(), *Context,
- Sysroot.empty() ? "" : Sysroot.c_str(),
- PPOpts.DisablePCHValidation,
- /*AllowASTWithCompilerErrors=*/false,
- /*AllowConfigurationMismatch=*/false,
- HSOpts.ModulesValidateSystemHeaders,
- getFrontendOpts().UseGlobalModuleIndex);
+ 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,
+ std::move(ReadTimer));
if (hasASTConsumer()) {
ModuleManager->setDeserializationListener(
getASTConsumer().GetASTDeserializationListener());
@@ -1268,12 +1266,18 @@ 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.
struct ReadModuleNames : ASTReaderListener {
CompilerInstance &CI;
std::vector<StringRef> ModuleFileStack;
+ std::vector<StringRef> ModuleNameStack;
bool Failed;
bool TopFileIsModule;
@@ -1283,21 +1287,37 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
bool needsImportVisitation() const override { return true; }
void visitImport(StringRef FileName) override {
+ if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) {
+ if (ModuleFileStack.size() == 0)
+ TopFileIsModule = true;
+ return;
+ }
+
ModuleFileStack.push_back(FileName);
+ ModuleNameStack.push_back(StringRef());
if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
+ *CI.getPCHContainerOperations(),
*this)) {
- CI.getDiagnostics().Report(SourceLocation(),
- diag::err_module_file_not_found)
+ CI.getDiagnostics().Report(
+ SourceLocation(), CI.getFileManager().getBufferForFile(FileName)
+ ? diag::err_module_file_invalid
+ : diag::err_module_file_not_found)
<< FileName;
- // FIXME: Produce a note stack explaining how we got here.
+ for (int I = ModuleFileStack.size() - 2; I >= 0; --I)
+ CI.getDiagnostics().Report(SourceLocation(),
+ diag::note_module_file_imported_by)
+ << ModuleFileStack[I]
+ << !ModuleNameStack[I].empty() << ModuleNameStack[I];
Failed = true;
}
+ ModuleNameStack.pop_back();
ModuleFileStack.pop_back();
}
void ReadModuleName(StringRef ModuleName) override {
if (ModuleFileStack.size() == 1)
TopFileIsModule = true;
+ ModuleNameStack.back() = ModuleName;
auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
if (!ModuleFile.empty() &&
@@ -1310,6 +1330,19 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
}
} RMN(*this);
+ // If we don't already have an ASTReader, create one now.
+ if (!ModuleManager)
+ createModuleManager();
+
+ // Tell the module manager about this module file.
+ if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {
+ getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)
+ << FileName;
+ return false;
+ }
+
+ // Build our mapping of module names to module files from this file
+ // and its imports.
RMN.visitImport(FileName);
if (RMN.Failed)
@@ -1343,7 +1376,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule &&
ModuleName != getLangOpts().ImplementationOfModule)
ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
- ImportLoc, /*Complain=*/false);
+ ImportLoc);
return LastModuleImportResult;
}
@@ -1373,6 +1406,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
auto Override = ModuleFileOverrides.find(ModuleName);
bool Explicit = Override != ModuleFileOverrides.end();
+ if (!Explicit && !getLangOpts().ImplicitModules) {
+ getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
+ << ModuleName;
+ ModuleBuildFailed = true;
+ return ModuleLoadResult();
+ }
std::string ModuleFileName =
Explicit ? Override->second
@@ -1391,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;
@@ -1580,8 +1624,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
- ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc,
- /*Complain=*/true);
+ ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
}
// Check for any configuration macros that have changed.
@@ -1591,25 +1634,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module, ImportLoc);
}
- // Determine whether we're in the #include buffer for a module. The #includes
- // in that buffer do not qualify as module imports; they're just an
- // implementation detail of us building the module.
- bool IsInModuleIncludes = !getLangOpts().CurrentModule.empty() &&
- getSourceManager().getFileID(ImportLoc) ==
- getSourceManager().getMainFileID();
-
- // If this module import was due to an inclusion directive, create an
- // implicit import declaration to capture it in the AST.
- if (IsInclusionDirective && hasASTContext() && !IsInModuleIncludes) {
- TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
- ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
- ImportLoc, Module,
- Path.back().second);
- TU->addDecl(ImportD);
- if (Consumer)
- Consumer->HandleImplicitImportDecl(ImportD);
- }
-
LastModuleImportLoc = ImportLoc;
LastModuleImportResult = ModuleLoadResult(Module, false);
return LastModuleImportResult;
@@ -1617,9 +1641,13 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
void CompilerInstance::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind Visibility,
- SourceLocation ImportLoc,
- bool Complain){
- ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain);
+ SourceLocation ImportLoc) {
+ if (!ModuleManager)
+ createModuleManager();
+ if (!ModuleManager)
+ return;
+
+ ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc);
}
GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
@@ -1639,8 +1667,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
llvm::sys::fs::create_directories(
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
GlobalModuleIndex::writeIndex(
- getFileManager(),
- getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ getFileManager(), *getPCHContainerOperations(),
+ getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
ModuleManager->resetForReload();
ModuleManager->loadGlobalIndex();
GlobalIndex = ModuleManager->getGlobalIndex();
@@ -1667,8 +1695,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
}
if (RecreateIndex) {
GlobalModuleIndex::writeIndex(
- getFileManager(),
- getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ getFileManager(), *getPCHContainerOperations(),
+ getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
ModuleManager->resetForReload();
ModuleManager->loadGlobalIndex();
GlobalIndex = ModuleManager->getGlobalIndex();
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 54025b0..6f13faf 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -126,7 +126,7 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
} else {
// Otherwise, add its value (for OPT_W_Joined and similar).
for (const char *Arg : A->getValues())
- Diagnostics.push_back(Arg);
+ Diagnostics.emplace_back(Arg);
}
}
}
@@ -239,10 +239,8 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.InlineMaxStackDepth, Diags);
Opts.CheckersControlList.clear();
- for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker,
- OPT_analyzer_disable_checker),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A :
+ Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
A->claim();
bool enable = (A->getOption().getID() == OPT_analyzer_checker);
// We can have a list of comma separated checker names, e.g:
@@ -250,14 +248,12 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
StringRef checkerList = A->getValue();
SmallVector<StringRef, 4> checkers;
checkerList.split(checkers, ",");
- for (unsigned i = 0, e = checkers.size(); i != e; ++i)
- Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
+ for (StringRef checker : checkers)
+ Opts.CheckersControlList.emplace_back(checker, enable);
}
-
+
// Go through the analyzer configuration options.
- for (arg_iterator it = Args.filtered_begin(OPT_analyzer_config),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A : Args.filtered(OPT_analyzer_config)) {
A->claim();
// We can have a list of comma separated config names, e.g:
// '-analyzer-config key1=val1,key2=val2'
@@ -325,15 +321,35 @@ GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
return Pattern;
}
+static bool parseDiagnosticLevelMask(StringRef FlagName,
+ const std::vector<std::string> &Levels,
+ DiagnosticsEngine *Diags,
+ DiagnosticLevelMask &M) {
+ bool Success = true;
+ for (const auto &Level : Levels) {
+ DiagnosticLevelMask const PM =
+ llvm::StringSwitch<DiagnosticLevelMask>(Level)
+ .Case("note", DiagnosticLevelMask::Note)
+ .Case("remark", DiagnosticLevelMask::Remark)
+ .Case("warning", DiagnosticLevelMask::Warning)
+ .Case("error", DiagnosticLevelMask::Error)
+ .Default(DiagnosticLevelMask::None);
+ if (PM == DiagnosticLevelMask::None) {
+ Success = false;
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_value) << FlagName << Level;
+ }
+ M = M | PM;
+ }
+ return Success;
+}
+
static void parseSanitizerKinds(StringRef FlagName,
const std::vector<std::string> &Sanitizers,
DiagnosticsEngine &Diags, SanitizerSet &S) {
for (const auto &Sanitizer : Sanitizers) {
- SanitizerKind K = llvm::StringSwitch<SanitizerKind>(Sanitizer)
-#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
-#include "clang/Basic/Sanitizers.def"
- .Default(SanitizerKind::Unknown);
- if (K == SanitizerKind::Unknown)
+ SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
+ if (K == 0)
Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
else
S.set(K, true);
@@ -367,6 +383,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ?
CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining());
+ if (Arg *A = Args.getLastArg(OPT_fveclib)) {
+ StringRef Name = A->getValue();
+ if (Name == "Accelerate")
+ Opts.setVecLib(CodeGenOptions::Accelerate);
+ else if (Name == "none")
+ Opts.setVecLib(CodeGenOptions::NoLibrary);
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ }
+
if (Args.hasArg(OPT_gline_tables_only)) {
Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
} else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
@@ -395,6 +421,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
// Default Dwarf version is 4 if we are generating debug information.
Opts.DwarfVersion = 4;
+ if (const Arg *A =
+ Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
+ Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
+
Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
@@ -417,13 +447,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as);
Opts.Autolink = !Args.hasArg(OPT_fno_autolink);
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
- Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate);
+ Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate) ||
+ Args.hasArg(OPT_fprofile_instr_generate_EQ);
+ Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ);
Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
Opts.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
- Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
Opts.CodeModel = getCodeModel(Args, Diags);
@@ -441,11 +472,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
- Opts.NoSignedZeros = Args.hasArg(OPT_cl_no_signed_zeros);
+ Opts.NoSignedZeros = Args.hasArg(OPT_fno_signed_zeros);
+ Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
- Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
@@ -472,8 +503,15 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
OPT_fno_function_sections, false);
Opts.DataSections = Args.hasFlag(OPT_fdata_sections,
OPT_fno_data_sections, false);
+ Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names,
+ OPT_fno_unique_section_names, true);
+
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);
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp);
@@ -489,6 +527,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
Opts.CoverageNoFunctionNamesInData =
Args.hasArg(OPT_coverage_no_function_names_in_data);
+ Opts.CoverageExitBlockBeforeBody =
+ Args.hasArg(OPT_coverage_exit_block_before_body);
if (Args.hasArg(OPT_coverage_version_EQ)) {
StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
if (CoverageVersion.size() != 4) {
@@ -507,12 +547,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
- Opts.SanitizeCoverage =
- getLastArgIntValue(Args, OPT_fsanitize_coverage, 0, Diags);
+ Opts.SanitizeCoverageType =
+ getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags);
+ Opts.SanitizeCoverageIndirectCalls =
+ Args.hasArg(OPT_fsanitize_coverage_indirect_calls);
+ Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb);
+ Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp);
+ Opts.SanitizeCoverage8bitCounters =
+ Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
- Opts.SanitizeUndefinedTrapOnError =
- Args.hasArg(OPT_fsanitize_undefined_trap_on_error);
+ 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);
@@ -523,6 +569,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.StackAlignment = StackAlignment;
}
+ if (Arg *A = Args.getLastArg(OPT_mstack_probe_size)) {
+ StringRef Val = A->getValue();
+ unsigned StackProbeSize = Opts.StackProbeSize;
+ Val.getAsInteger(0, StackProbeSize);
+ Opts.StackProbeSize = StackProbeSize;
+ }
+
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
StringRef Name = A->getValue();
unsigned Method = llvm::StringSwitch<unsigned>(Name)
@@ -615,6 +668,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
parseSanitizerKinds("-fsanitize-recover=",
Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
Opts.SanitizeRecover);
+ parseSanitizerKinds("-fsanitize-trap=",
+ Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
+ Opts.SanitizeTrap);
+
+ Opts.CudaGpuBinaryFileNames =
+ Args.getAllArgValues(OPT_fcuda_include_gpubinary);
return Success;
}
@@ -634,6 +693,8 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
Opts.ModuleDependencyOutputDir =
Args.getLastArgValue(OPT_module_dependency_dir);
+ if (Args.hasArg(OPT_MV))
+ Opts.OutputFormat = DependencyOutputFormat::NMake;
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
@@ -702,9 +763,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
if (Format == "clang")
Opts.setFormat(DiagnosticOptions::Clang);
else if (Format == "msvc")
- Opts.setFormat(DiagnosticOptions::Msvc);
+ Opts.setFormat(DiagnosticOptions::MSVC);
else if (Format == "msvc-fallback") {
- Opts.setFormat(DiagnosticOptions::Msvc);
+ Opts.setFormat(DiagnosticOptions::MSVC);
Opts.CLFallbackMode = true;
} else if (Format == "vi")
Opts.setFormat(DiagnosticOptions::Vi);
@@ -715,11 +776,18 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
<< Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
<< Format;
}
-
+
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
+ Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
+ Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
+ Diags, DiagMask);
+ if (Args.hasArg(OPT_verify_ignore_unexpected))
+ DiagMask = DiagnosticLevelMask::All;
+ Opts.setVerifyIgnoreUnexpected(DiagMask);
Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);
Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);
Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags);
@@ -830,26 +898,21 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
}
if (const Arg* A = Args.getLastArg(OPT_plugin)) {
- Opts.Plugins.push_back(A->getValue(0));
+ Opts.Plugins.emplace_back(A->getValue(0));
Opts.ProgramAction = frontend::PluginAction;
Opts.ActionName = A->getValue();
- for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
- end = Args.filtered_end(); it != end; ++it) {
- if ((*it)->getValue(0) == Opts.ActionName)
- Opts.PluginArgs.push_back((*it)->getValue(1));
- }
+ for (const Arg *AA : Args.filtered(OPT_plugin_arg))
+ if (AA->getValue(0) == Opts.ActionName)
+ Opts.PluginArgs.emplace_back(AA->getValue(1));
}
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
Opts.AddPluginArgs.resize(Opts.AddPluginActions.size());
- for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
- for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
- end = Args.filtered_end(); it != end; ++it) {
- if ((*it)->getValue(0) == Opts.AddPluginActions[i])
- Opts.AddPluginArgs[i].push_back((*it)->getValue(1));
- }
- }
+ for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i)
+ for (const Arg *A : Args.filtered(OPT_plugin_arg))
+ if (A->getValue(0) == Opts.AddPluginActions[i])
+ Opts.AddPluginArgs[i].emplace_back(A->getValue(1));
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
Opts.CodeCompletionAt =
@@ -966,6 +1029,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Case("cpp-output", IK_PreprocessedC)
.Case("assembler-with-cpp", IK_Asm)
.Case("c++-cpp-output", IK_PreprocessedCXX)
+ .Case("cuda-cpp-output", IK_PreprocessedCuda)
.Case("objective-c-cpp-output", IK_PreprocessedObjC)
.Case("objc-cpp-output", IK_PreprocessedObjC)
.Case("objective-c++-cpp-output", IK_PreprocessedObjCXX)
@@ -997,7 +1061,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (i == 0)
DashX = IK;
}
- Opts.Inputs.push_back(FrontendInputFile(Inputs[i], IK));
+ Opts.Inputs.emplace_back(std::move(Inputs[i]), IK);
}
return DashX;
@@ -1036,8 +1100,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path);
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
- // -fmodules implies -fmodule-maps
- Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules);
+ Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
Opts.ModuleCachePruneInterval =
getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60);
@@ -1050,98 +1113,77 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.ModulesValidateSystemHeaders =
Args.hasArg(OPT_fmodules_validate_system_headers);
- for (arg_iterator it = Args.filtered_begin(OPT_fmodules_ignore_macro),
- ie = Args.filtered_end();
- it != ie; ++it) {
- StringRef MacroDef = (*it)->getValue();
+ for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) {
+ StringRef MacroDef = A->getValue();
Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first);
}
// Add -I..., -F..., and -index-header-map options in order.
bool IsIndexHeaderMap = false;
- for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F,
- OPT_index_header_map),
- ie = Args.filtered_end(); it != ie; ++it) {
- if ((*it)->getOption().matches(OPT_index_header_map)) {
+ for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
+ if (A->getOption().matches(OPT_index_header_map)) {
// -index-header-map applies to the next -I or -F.
IsIndexHeaderMap = true;
continue;
}
-
- frontend::IncludeDirGroup Group
- = IsIndexHeaderMap? frontend::IndexHeaderMap : frontend::Angled;
-
- Opts.AddPath((*it)->getValue(), Group,
- /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true);
+
+ frontend::IncludeDirGroup Group =
+ IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;
+
+ Opts.AddPath(A->getValue(), Group,
+ /*IsFramework=*/A->getOption().matches(OPT_F), true);
IsIndexHeaderMap = false;
}
// Add -iprefix/-iwithprefix/-iwithprefixbefore options.
StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
- for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix,
- OPT_iwithprefixbefore),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A :
+ Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
if (A->getOption().matches(OPT_iprefix))
Prefix = A->getValue();
else if (A->getOption().matches(OPT_iwithprefix))
- Opts.AddPath(Prefix.str() + A->getValue(),
- frontend::After, false, true);
+ Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
else
- Opts.AddPath(Prefix.str() + A->getValue(),
- frontend::Angled, false, true);
- }
-
- for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::After, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_iquote),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::Quoted, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_isystem,
- OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::System, false,
- !(*it)->getOption().matches(OPT_iwithsysroot));
- for (arg_iterator it = Args.filtered_begin(OPT_iframework),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::System, true, true);
+ Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
+ }
+
+ for (const Arg *A : Args.filtered(OPT_idirafter))
+ Opts.AddPath(A->getValue(), frontend::After, false, true);
+ for (const Arg *A : Args.filtered(OPT_iquote))
+ Opts.AddPath(A->getValue(), frontend::Quoted, false, true);
+ for (const Arg *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
+ Opts.AddPath(A->getValue(), frontend::System, false,
+ !A->getOption().matches(OPT_iwithsysroot));
+ for (const Arg *A : Args.filtered(OPT_iframework))
+ Opts.AddPath(A->getValue(), frontend::System, true, true);
// Add the paths for the various language specific isystem flags.
- for (arg_iterator it = Args.filtered_begin(OPT_c_isystem),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::CSystem, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::CXXSystem, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_objc_isystem),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::ObjCSystem, false,true);
- for (arg_iterator it = Args.filtered_begin(OPT_objcxx_isystem),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(), frontend::ObjCXXSystem, false, true);
+ for (const Arg *A : Args.filtered(OPT_c_isystem))
+ Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
+ for (const Arg *A : Args.filtered(OPT_cxx_isystem))
+ Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
+ for (const Arg *A : Args.filtered(OPT_objc_isystem))
+ Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
+ for (const Arg *A : Args.filtered(OPT_objcxx_isystem))
+ Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
// Add the internal paths from a driver that detects standard include paths.
- for (arg_iterator I = Args.filtered_begin(OPT_internal_isystem,
- OPT_internal_externc_isystem),
- E = Args.filtered_end();
- I != E; ++I) {
+ for (const Arg *A :
+ Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
frontend::IncludeDirGroup Group = frontend::System;
- if ((*I)->getOption().matches(OPT_internal_externc_isystem))
+ if (A->getOption().matches(OPT_internal_externc_isystem))
Group = frontend::ExternCSystem;
- Opts.AddPath((*I)->getValue(), Group, false, true);
+ Opts.AddPath(A->getValue(), Group, false, true);
}
// Add the path prefixes which are implicitly treated as being system headers.
- for (arg_iterator I = Args.filtered_begin(OPT_system_header_prefix,
- OPT_no_system_header_prefix),
- E = Args.filtered_end();
- I != E; ++I)
+ for (const Arg *A :
+ Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
Opts.AddSystemHeaderPrefix(
- (*I)->getValue(), (*I)->getOption().matches(OPT_system_header_prefix));
+ A->getValue(), A->getOption().matches(OPT_system_header_prefix));
- for (arg_iterator I = Args.filtered_begin(OPT_ivfsoverlay),
- E = Args.filtered_end(); I != E; ++I)
- Opts.AddVFSOverlayFile((*I)->getValue());
+ for (const Arg *A : Args.filtered(OPT_ivfsoverlay))
+ Opts.AddVFSOverlayFile(A->getValue());
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
@@ -1169,6 +1211,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
LangStd = LangStandard::lang_opencl;
break;
case IK_CUDA:
+ case IK_PreprocessedCuda:
LangStd = LangStandard::lang_cuda;
break;
case IK_Asm:
@@ -1197,7 +1240,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.CPlusPlus1z = Std.isCPlusPlus1z();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
- Opts.GNUInline = !Std.isC99();
+ Opts.GNUInline = Std.isC89();
Opts.HexFloats = Std.hasHexFloats();
Opts.ImplicitInt = Std.hasImplicitInt();
@@ -1221,7 +1264,8 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.NativeHalfType = 1;
}
- Opts.CUDA = LangStd == LangStandard::lang_cuda || IK == IK_CUDA;
+ Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda ||
+ LangStd == LangStandard::lang_cuda;
// OpenCL and C++ both have bool, true, false keywords.
Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
@@ -1236,9 +1280,6 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.CXXOperatorNames = Opts.CPlusPlus;
Opts.DollarIdents = !Opts.AsmPreprocessor;
-
- // C++14 onwards has sized global deallocation functions.
- Opts.SizedDeallocation = Opts.CPlusPlus14;
}
/// Attempt to parse a visibility value out of the given argument.
@@ -1259,43 +1300,6 @@ static Visibility parseVisibility(Arg *arg, ArgList &args,
return DefaultVisibility;
}
-static unsigned parseMSCVersion(ArgList &Args, DiagnosticsEngine &Diags) {
- auto Arg = Args.getLastArg(OPT_fms_compatibility_version);
- if (!Arg)
- return 0;
-
- // The MSC versioning scheme involves four versioning components:
- // - Major
- // - Minor
- // - Build
- // - Patch
- //
- // We accept either the old style (_MSC_VER) value, or a _MSC_FULL_VER value.
- // Additionally, the value may be provided in the form of a more readable
- // MM.mm.bbbbb.pp version.
- //
- // Unfortunately, due to the bit-width limitations, we cannot currently encode
- // the value for the patch level.
-
- unsigned VC[4] = {0};
- StringRef Value = Arg->getValue();
- SmallVector<StringRef, 4> Components;
-
- Value.split(Components, ".", llvm::array_lengthof(VC));
- for (unsigned CI = 0,
- CE = std::min(Components.size(), llvm::array_lengthof(VC));
- CI < CE; ++CI) {
- if (Components[CI].getAsInteger(10, VC[CI])) {
- Diags.Report(diag::err_drv_invalid_value)
- << Arg->getAsString(Args) << Value;
- return 0;
- }
- }
-
- // FIXME we cannot encode the patch level
- return VC[0] * 10000000 + VC[1] * 100000 + VC[2];
-}
-
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
// FIXME: Cleanup per-file based stuff.
@@ -1336,6 +1340,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
<< A->getAsString(Args) << "OpenCL";
break;
case IK_CUDA:
+ case IK_PreprocessedCuda:
if (!Std.isCPlusPlus())
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args) << "CUDA";
@@ -1381,6 +1386,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fcuda_is_device))
Opts.CUDAIsDevice = 1;
+ if (Args.hasArg(OPT_fcuda_allow_host_calls_from_host_device))
+ Opts.CUDAAllowHostCallsFromHostDevice = 1;
+
+ if (Args.hasArg(OPT_fcuda_disable_target_call_checks))
+ Opts.CUDADisableTargetCallChecks = 1;
+
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
@@ -1412,8 +1423,13 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
(Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
}
- if (Args.hasArg(OPT_fgnu89_inline))
- Opts.GNUInline = 1;
+ if (Args.hasArg(OPT_fgnu89_inline)) {
+ if (Opts.CPlusPlus)
+ Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline"
+ << "C++/ObjC++";
+ else
+ Opts.GNUInline = 1;
+ }
if (Args.hasArg(OPT_fapple_kext)) {
if (!Opts.CPlusPlus)
@@ -1462,7 +1478,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
- Opts.MSCompatibilityVersion = parseMSCVersion(Args, Diags);
+ Opts.MSCompatibilityVersion = 0;
+ if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
+ VersionTuple VT;
+ if (VT.tryParse(A->getValue()))
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << A->getValue();
+ Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
+ VT.getMinor().getValueOr(0) * 100000 +
+ VT.getSubminor().getValueOr(0);
+ }
// Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
@@ -1498,12 +1523,15 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
Opts.ModulesDeclUse =
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
+ Opts.ModulesLocalVisibility =
+ Args.hasArg(OPT_fmodules_local_submodule_visibility);
+ Opts.ModulesHideInternalLinkage =
+ !Args.hasArg(OPT_fno_modules_hide_internal_linkage);
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
Opts.ModulesErrorRecovery = !Args.hasArg(OPT_fno_modules_error_recovery);
- Opts.ModulesImplicitMaps = Args.hasFlag(OPT_fmodules_implicit_maps,
- OPT_fno_modules_implicit_maps, true);
+ Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
@@ -1512,7 +1540,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
- Opts.SizedDeallocation |= Args.hasArg(OPT_fsized_deallocation);
+ Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
+ Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts);
Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
@@ -1559,10 +1588,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name);
+ Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
Opts.ImplementationOfModule =
Args.getLastArgValue(OPT_fmodule_implementation_of);
- Opts.NativeHalfType = Opts.NativeHalfType;
+ Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
+ std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
+ Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns);
+ Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm);
if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() &&
Opts.CurrentModule != Opts.ImplementationOfModule) {
@@ -1570,6 +1603,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
<< Opts.CurrentModule << Opts.ImplementationOfModule;
}
+ // For now, we only support local submodule visibility in C++ (because we
+ // heavily depend on the ODR for merging redefinitions).
+ if (Opts.ModulesLocalVisibility && !Opts.CPlusPlus)
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << "-fmodules-local-submodule-visibility" << "C";
+
if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) {
switch (llvm::StringSwitch<unsigned>(A->getValue())
.Case("target", LangOptions::ASMM_Target)
@@ -1610,12 +1649,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel);
}
- // Check if -fopenmp= is specified.
- if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
- Opts.OpenMP = llvm::StringSwitch<bool>(A->getValue())
- .Case("libiomp5", true)
- .Default(false);
- }
+ // 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,
@@ -1660,7 +1697,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// -fsanitize-address-field-padding=N has to be a LangOpt, parse it here.
Opts.SanitizeAddressFieldPadding =
getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
- Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist);
+ Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
@@ -1678,11 +1715,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
- for (arg_iterator it = Args.filtered_begin(OPT_error_on_deserialized_pch_decl),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
+ for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
- }
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
StringRef Value(A->getValue());
@@ -1701,38 +1735,28 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
}
// Add macros from the command line.
- for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
- ie = Args.filtered_end(); it != ie; ++it) {
- if ((*it)->getOption().matches(OPT_D))
- Opts.addMacroDef((*it)->getValue());
+ for (const Arg *A : Args.filtered(OPT_D, OPT_U)) {
+ if (A->getOption().matches(OPT_D))
+ Opts.addMacroDef(A->getValue());
else
- Opts.addMacroUndef((*it)->getValue());
+ Opts.addMacroUndef(A->getValue());
}
Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
// Add the ordered list of -includes.
- for (arg_iterator it = Args.filtered_begin(OPT_include),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- Opts.Includes.push_back(A->getValue());
- }
+ for (const Arg *A : Args.filtered(OPT_include))
+ Opts.Includes.emplace_back(A->getValue());
- for (arg_iterator it = Args.filtered_begin(OPT_chain_include),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- Opts.ChainedIncludes.push_back(A->getValue());
- }
+ for (const Arg *A : Args.filtered(OPT_chain_include))
+ Opts.ChainedIncludes.emplace_back(A->getValue());
// Include 'altivec.h' if -faltivec option present
if (Args.hasArg(OPT_faltivec))
- Opts.Includes.push_back("altivec.h");
+ Opts.Includes.emplace_back("altivec.h");
- for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- std::pair<StringRef,StringRef> Split =
- StringRef(A->getValue()).split(';');
+ for (const Arg *A : Args.filtered(OPT_remap_file)) {
+ std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
if (Split.second.empty()) {
Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
@@ -1741,7 +1765,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.addRemappedFile(Split.first, Split.second);
}
-
+
if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) {
StringRef Name = A->getValue();
unsigned Library = llvm::StringSwitch<unsigned>(Name)
@@ -1805,6 +1829,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
+ Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
}
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
@@ -1815,7 +1840,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
-
+ Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
// Use the default target triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getDefaultTargetTriple();
@@ -1831,39 +1856,37 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
std::unique_ptr<OptTable> Opts(createDriverOptTable());
const unsigned IncludedFlagsBitmask = options::CC1Option;
unsigned MissingArgIndex, MissingArgCount;
- std::unique_ptr<InputArgList> Args(
- Opts->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount,
- IncludedFlagsBitmask));
+ InputArgList Args =
+ Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex,
+ MissingArgCount, IncludedFlagsBitmask);
// Check for missing argument error.
if (MissingArgCount) {
Diags.Report(diag::err_drv_missing_argument)
- << Args->getArgString(MissingArgIndex) << MissingArgCount;
+ << Args.getArgString(MissingArgIndex) << MissingArgCount;
Success = false;
}
// Issue errors on unknown arguments.
- for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
- ie = Args->filtered_end(); it != ie; ++it) {
- Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
+ for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
+ Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
Success = false;
}
- Success = ParseAnalyzerArgs(*Res.getAnalyzerOpts(), *Args, Diags) && Success;
- Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
- ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
- Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, &Diags)
- && Success;
- ParseCommentArgs(Res.getLangOpts()->CommentOpts, *Args);
- ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
+ Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
+ Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args);
+ ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
+ Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags);
+ ParseCommentArgs(Res.getLangOpts()->CommentOpts, Args);
+ ParseFileSystemArgs(Res.getFileSystemOpts(), Args);
// FIXME: We shouldn't have to pass the DashX option around here
- InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
- ParseTargetArgs(Res.getTargetOpts(), *Args);
- Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags,
- Res.getTargetOpts()) && Success;
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
+ InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags);
+ ParseTargetArgs(Res.getTargetOpts(), Args);
+ Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
+ Res.getTargetOpts());
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args);
if (DashX != IK_AST && DashX != IK_LLVM_IR) {
- ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
+ ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
Res.getLangOpts()->ObjCExceptions = 1;
}
@@ -1872,8 +1895,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
// ParsePreprocessorArgs and remove the FileManager
// parameters from the function and the "FileManager.h" #include.
FileManager FileMgr(Res.getFileSystemOpts());
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
- ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args,
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags);
+ ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction);
return Success;
}
@@ -1951,6 +1974,9 @@ std::string CompilerInvocation::getModuleHash() const {
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
+
+ for (StringRef Feature : LangOpts->ModuleFeatures)
+ code = hash_combine(code, Feature);
// Extend the signature with the target options.
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
@@ -2002,7 +2028,7 @@ std::string CompilerInvocation::getModuleHash() const {
llvm::sys::path::append(systemVersionFile, "SystemVersion.plist");
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
- llvm::MemoryBuffer::getFile(systemVersionFile.str());
+ llvm::MemoryBuffer::getFile(systemVersionFile);
if (buffer) {
code = hash_combine(code, buffer.get()->getBuffer());
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 4a8a8a0..2afd23f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
index 6ea8f51..0995ab4 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
@@ -150,6 +150,8 @@ class DFGImpl : public PPCallbacks {
bool AddMissingHeaderDeps;
bool SeenMissingHeader;
bool IncludeModuleFiles;
+ DependencyOutputFormat OutputFormat;
+
private:
bool FileMatchesDepCriteria(const char *Filename,
SrcMgr::CharacteristicKind FileType);
@@ -162,7 +164,8 @@ public:
PhonyTarget(Opts.UsePhonyTargets),
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
SeenMissingHeader(false),
- IncludeModuleFiles(Opts.IncludeModuleFiles) {}
+ IncludeModuleFiles(Opts.IncludeModuleFiles),
+ OutputFormat(Opts.OutputFormat) {}
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -289,13 +292,76 @@ void DFGImpl::AddFilename(StringRef Filename) {
Files.push_back(Filename);
}
-/// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
-/// other scary characters.
-static void PrintFilename(raw_ostream &OS, StringRef Filename) {
+/// Print the filename, with escaping or quoting that accommodates the three
+/// most likely tools that use dependency files: GNU Make, BSD Make, and
+/// NMake/Jom.
+///
+/// BSD Make is the simplest case: It does no escaping at all. This means
+/// characters that are normally delimiters, i.e. space and # (the comment
+/// character) simply aren't supported in filenames.
+///
+/// GNU Make does allow space and # in filenames, but to avoid being treated
+/// as a delimiter or comment, these must be escaped with a backslash. Because
+/// backslash is itself the escape character, if a backslash appears in a
+/// filename, it should be escaped as well. (As a special case, $ is escaped
+/// as $$, which is the normal Make way to handle the $ character.)
+/// For compatibility with BSD Make and historical practice, if GNU Make
+/// un-escapes characters in a filename but doesn't find a match, it will
+/// retry with the unmodified original string.
+///
+/// GCC tries to accommodate both Make formats by escaping any space or #
+/// characters in the original filename, but not escaping backslashes. The
+/// apparent intent is so that filenames with backslashes will be handled
+/// correctly by BSD Make, and by GNU Make in its fallback mode of using the
+/// unmodified original string; filenames with # or space characters aren't
+/// supported by BSD Make at all, but will be handled correctly by GNU Make
+/// due to the escaping.
+///
+/// A corner case that GCC gets only partly right is when the original filename
+/// has a backslash immediately followed by space or #. GNU Make would expect
+/// this backslash to be escaped; however GCC escapes the original backslash
+/// only when followed by space, not #. It will therefore take a dependency
+/// from a directive such as
+/// #include "a\ b\#c.h"
+/// and emit it as
+/// a\\\ b\\#c.h
+/// which GNU Make will interpret as
+/// a\ b\
+/// followed by a comment. Failing to find this file, it will fall back to the
+/// original string, which probably doesn't exist either; in any case it won't
+/// find
+/// a\ b\#c.h
+/// which is the actual filename specified by the include directive.
+///
+/// Clang does what GCC does, rather than what GNU Make expects.
+///
+/// NMake/Jom has a different set of scary characters, but wraps filespecs in
+/// double-quotes to avoid misinterpreting them; see
+/// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info,
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+/// for Windows file-naming info.
+static void PrintFilename(raw_ostream &OS, StringRef Filename,
+ DependencyOutputFormat OutputFormat) {
+ if (OutputFormat == DependencyOutputFormat::NMake) {
+ // Add quotes if needed. These are the characters listed as "special" to
+ // NMake, that are legal in a Windows filespec, and that could cause
+ // misinterpretation of the dependency string.
+ if (Filename.find_first_of(" #${}^!") != StringRef::npos)
+ OS << '\"' << Filename << '\"';
+ else
+ OS << Filename;
+ return;
+ }
+ assert(OutputFormat == DependencyOutputFormat::Make);
for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
- if (Filename[i] == ' ' || Filename[i] == '#')
+ if (Filename[i] == '#') // Handle '#' the broken gcc way.
+ OS << '\\';
+ else if (Filename[i] == ' ') { // Handle space correctly.
OS << '\\';
- else if (Filename[i] == '$') // $ is escaped by $$.
+ unsigned j = i;
+ while (j > 0 && Filename[--j] == '\\')
+ OS << '\\';
+ } else if (Filename[i] == '$') // $ is escaped by $$.
OS << '$';
OS << Filename[i];
}
@@ -354,7 +420,7 @@ void DFGImpl::OutputDependencyFile() {
Columns = 2;
}
OS << ' ';
- PrintFilename(OS, *I);
+ PrintFilename(OS, *I, OutputFormat);
Columns += N + 1;
}
OS << '\n';
@@ -365,7 +431,7 @@ void DFGImpl::OutputDependencyFile() {
for (std::vector<std::string>::iterator I = Files.begin() + 1,
E = Files.end(); I != E; ++I) {
OS << '\n';
- PrintFilename(OS, *I);
+ PrintFilename(OS, *I, OutputFormat);
OS << ":\n";
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
index c81c81a..db9dd3b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -44,7 +44,7 @@ public:
explicit DelegatingDeserializationListener(
ASTDeserializationListener *Previous, bool DeletePrevious)
: Previous(Previous), DeletePrevious(DeletePrevious) {}
- virtual ~DelegatingDeserializationListener() {
+ ~DelegatingDeserializationListener() override {
if (DeletePrevious)
delete Previous;
}
@@ -71,7 +71,7 @@ public:
Previous->SelectorRead(ID, Sel);
}
void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,
- MacroDefinition *MD) override {
+ MacroDefinitionRecord *MD) override {
if (Previous)
Previous->MacroDefinitionRead(PPID, MD);
}
@@ -191,7 +191,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
std::unique_ptr<ASTUnit> AST =
- ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts());
+ ASTUnit::LoadFromASTFile(InputFile, CI.getPCHContainerOperations(),
+ Diags, CI.getFileSystemOpts());
if (!AST)
goto failure;
@@ -262,18 +263,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
FileManager &FileMgr = CI.getFileManager();
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
+ std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(PCHDir->getName(), DirNative);
bool Found = false;
- for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
+ for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Check whether this is an acceptable AST file.
- if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
- CI.getLangOpts(),
- CI.getTargetOpts(),
- CI.getPreprocessorOpts())) {
+ if (ASTReader::isAcceptableASTFile(
+ Dir->path(), FileMgr, *CI.getPCHContainerOperations(),
+ CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
+ SpecificModuleCachePath)) {
PPOpts.ImplicitPCHInclude = Dir->path();
Found = true;
break;
@@ -383,6 +385,15 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
"doesn't support modules");
}
+ // If we were asked to load any module map files, do so now.
+ for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {
+ if (auto *File = CI.getFileManager().getFile(Filename))
+ CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(
+ File, /*IsSystem*/false);
+ else
+ CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
+ }
+
// If we were asked to load any module files, do so now.
for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
if (!CI.loadModuleFile(ModuleFile))
@@ -432,8 +443,8 @@ bool FrontendAction::Execute() {
if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&
CI.hasPreprocessor()) {
GlobalModuleIndex::writeIndex(
- CI.getFileManager(),
- CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ CI.getFileManager(), *CI.getPCHContainerOperations(),
+ CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
}
return true;
@@ -457,16 +468,12 @@ void FrontendAction::EndSourceFile() {
// FIXME: There is more per-file stuff we could just drop here?
bool DisableFree = CI.getFrontendOpts().DisableFree;
if (DisableFree) {
- if (!isCurrentFileAST()) {
- CI.resetAndLeakSema();
- CI.resetAndLeakASTContext();
- }
+ CI.resetAndLeakSema();
+ CI.resetAndLeakASTContext();
BuryPointer(CI.takeASTConsumer().get());
} else {
- if (!isCurrentFileAST()) {
- CI.setSema(nullptr);
- CI.setASTContext(nullptr);
- }
+ CI.setSema(nullptr);
+ CI.setASTContext(nullptr);
CI.setASTConsumer(nullptr);
}
@@ -483,13 +490,16 @@ void FrontendAction::EndSourceFile() {
// FrontendAction.
CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());
- // FIXME: Only do this if DisableFree is set.
if (isCurrentFileAST()) {
- CI.resetAndLeakSema();
- CI.resetAndLeakASTContext();
- CI.resetAndLeakPreprocessor();
- CI.resetAndLeakSourceManager();
- CI.resetAndLeakFileManager();
+ if (DisableFree) {
+ CI.resetAndLeakPreprocessor();
+ CI.resetAndLeakSourceManager();
+ CI.resetAndLeakFileManager();
+ } else {
+ CI.setPreprocessor(nullptr);
+ CI.setSourceManager(nullptr);
+ CI.setFileManager(nullptr);
+ }
}
setCompilerInstance(nullptr);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
index 701ef02..4997764 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Pragma.h"
@@ -79,38 +80,48 @@ std::unique_ptr<ASTConsumer>
GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
+ raw_pwrite_stream *OS =
+ ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
- return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
- nullptr, Sysroot, OS);
+
+ auto Buffer = std::make_shared<PCHBuffer>();
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(llvm::make_unique<PCHGenerator>(
+ CI.getPreprocessor(), OutputFile, nullptr, Sysroot, Buffer));
+ Consumers.push_back(
+ CI.getPCHContainerOperations()->CreatePCHContainerGenerator(
+ CI.getDiagnostics(), CI.getHeaderSearchOpts(),
+ CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(),
+ InFile, OutputFile, OS, Buffer));
+
+ return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
-bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile,
- raw_ostream *&OS) {
+raw_pwrite_stream *GeneratePCHAction::ComputeASTConsumerArguments(
+ CompilerInstance &CI, StringRef InFile, std::string &Sysroot,
+ std::string &OutputFile) {
Sysroot = CI.getHeaderSearchOpts().Sysroot;
if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
- return true;
+ return nullptr;
}
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
- OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
- /*RemoveFileOnSignal=*/false, InFile,
- /*Extension=*/"", /*useTemporary=*/true);
+ raw_pwrite_stream *OS =
+ CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile,
+ /*Extension=*/"", /*useTemporary=*/true);
if (!OS)
- return true;
+ return nullptr;
OutputFile = CI.getFrontendOpts().OutputFile;
- return false;
+ return OS;
}
std::unique_ptr<ASTConsumer>
@@ -118,12 +129,21 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
- raw_ostream *OS = nullptr;
- if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
+ raw_pwrite_stream *OS =
+ ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ if (!OS)
return nullptr;
- return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
- Module, Sysroot, OS);
+ auto Buffer = std::make_shared<PCHBuffer>();
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(llvm::make_unique<PCHGenerator>(
+ CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer));
+ Consumers.push_back(
+ CI.getPCHContainerOperations()->CreatePCHContainerGenerator(
+ CI.getDiagnostics(), CI.getHeaderSearchOpts(),
+ CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(),
+ InFile, OutputFile, OS, Buffer));
+ return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
static SmallVectorImpl<char> &
@@ -151,22 +171,6 @@ static std::error_code addHeaderInclude(StringRef HeaderName,
return std::error_code();
}
-static std::error_code addHeaderInclude(const FileEntry *Header,
- SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts,
- bool IsExternC) {
- // Use an absolute path if we don't have a filename as written in the module
- // map file; this ensures that we will identify the right file independent of
- // header search paths.
- if (llvm::sys::path::is_absolute(Header->getName()))
- return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
-
- SmallString<256> AbsName(Header->getName());
- if (std::error_code Err = llvm::sys::fs::make_absolute(AbsName))
- return Err;
- return addHeaderInclude(AbsName, Includes, LangOpts, IsExternC);
-}
-
/// \brief Collect the set of header includes needed to construct the given
/// module and update the TopHeaders file set of the module.
///
@@ -195,21 +199,21 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
}
// Note that Module->PrivateHeaders will not be a TopHeader.
- if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
- // FIXME: Track the name as written here.
- Module->addTopHeader(UmbrellaHeader);
+ if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) {
+ Module->addTopHeader(UmbrellaHeader.Entry);
if (Module->Parent) {
// Include the umbrella header for submodules.
- if (std::error_code Err = addHeaderInclude(UmbrellaHeader, Includes,
- LangOpts, Module->IsExternC))
+ if (std::error_code Err = addHeaderInclude(UmbrellaHeader.NameAsWritten,
+ Includes, LangOpts,
+ Module->IsExternC))
return Err;
}
- } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
+ } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
std::error_code EC;
SmallString<128> DirNative;
- llvm::sys::path::native(UmbrellaDir->getName(), DirNative);
- for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative.str(), EC),
+ llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative);
+ for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative, EC),
DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Check whether this entry has an extension typically associated with
@@ -230,11 +234,20 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
if (ModMap.isHeaderUnavailableInModule(Header, Module))
continue;
+ // Compute the relative path from the directory to this file.
+ SmallVector<StringRef, 16> Components;
+ auto PathIt = llvm::sys::path::rbegin(Dir->path());
+ for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
+ Components.push_back(*PathIt);
+ SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
+ for (auto It = Components.rbegin(), End = Components.rend(); It != End;
+ ++It)
+ llvm::sys::path::append(RelativeHeader, *It);
+
// Include this header as part of the umbrella directory.
- // FIXME: Track the name as written through to here.
Module->addTopHeader(Header);
- if (std::error_code Err =
- addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
+ if (std::error_code Err = addHeaderInclude(RelativeHeader, Includes,
+ LangOpts, Module->IsExternC))
return Err;
}
@@ -326,10 +339,9 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
std::error_code Err = std::error_code();
- if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
- // FIXME: Track the file name as written.
- Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
- Module->IsExternC);
+ if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader())
+ Err = addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents,
+ CI.getLangOpts(), Module->IsExternC);
if (!Err)
Err = collectModuleHeaderIncludes(
CI.getLangOpts(), FileMgr,
@@ -355,11 +367,9 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return true;
}
-bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile,
- raw_ostream *&OS) {
+raw_pwrite_stream *GenerateModuleAction::ComputeASTConsumerArguments(
+ CompilerInstance &CI, StringRef InFile, std::string &Sysroot,
+ std::string &OutputFile) {
// If no output file was provided, figure out where this module would go
// in the module cache.
if (CI.getFrontendOpts().OutputFile.empty()) {
@@ -368,19 +378,20 @@ bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
HS.getModuleFileName(CI.getLangOpts().CurrentModule,
ModuleMapForUniquing->getName());
}
-
+
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
- OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
- /*RemoveFileOnSignal=*/false, InFile,
- /*Extension=*/"", /*useTemporary=*/true,
- /*CreateMissingDirectories=*/true);
+ raw_pwrite_stream *OS =
+ CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile,
+ /*Extension=*/"", /*useTemporary=*/true,
+ /*CreateMissingDirectories=*/true);
if (!OS)
- return true;
-
+ return nullptr;
+
OutputFile = CI.getFrontendOpts().OutputFile;
- return false;
+ return OS;
}
std::unique_ptr<ASTConsumer>
@@ -403,13 +414,13 @@ void VerifyPCHAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
- std::unique_ptr<ASTReader> Reader(
- new ASTReader(CI.getPreprocessor(), CI.getASTContext(),
- Sysroot.empty() ? "" : Sysroot.c_str(),
- /*DisableValidation*/ false,
- /*AllowPCHWithCompilerErrors*/ false,
- /*AllowConfigurationMismatch*/ true,
- /*ValidateSystemInputs*/ true));
+ std::unique_ptr<ASTReader> Reader(new ASTReader(
+ CI.getPreprocessor(), CI.getASTContext(), *CI.getPCHContainerOperations(),
+ Sysroot.empty() ? "" : Sysroot.c_str(),
+ /*DisableValidation*/ false,
+ /*AllowPCHWithCompilerErrors*/ false,
+ /*AllowConfigurationMismatch*/ true,
+ /*ValidateSystemInputs*/ true));
Reader->ReadAST(getCurrentFile(),
Preamble ? serialization::MK_Preamble
@@ -459,11 +470,18 @@ namespace {
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
+
+ if (!LangOpts.ModuleFeatures.empty()) {
+ Out.indent(4) << "Module features:\n";
+ for (StringRef Feature : LangOpts.ModuleFeatures)
+ Out.indent(6) << Feature << "\n";
+ }
+
return false;
}
- bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) override {
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
Out.indent(2) << "Target options:\n";
Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";
@@ -480,9 +498,8 @@ namespace {
return false;
}
- virtual bool
- ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
- bool Complain) override {
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override {
Out.indent(2) << "Diagnostic options:\n";
#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
@@ -501,9 +518,11 @@ namespace {
}
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
bool Complain) override {
Out.indent(2) << "Header search options:\n";
Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
+ Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
"Use builtin include directories [-nobuiltininc]");
DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
@@ -557,9 +576,9 @@ void DumpModuleInfoAction::ExecuteAction() {
Out << "Information for module file '" << getCurrentFile() << "':\n";
DumpModuleInfoListener Listener(Out);
- ASTReader::readASTFileControlBlock(getCurrentFile(),
- getCompilerInstance().getFileManager(),
- Listener);
+ ASTReader::readASTFileControlBlock(
+ getCurrentFile(), getCompilerInstance().getFileManager(),
+ *getCompilerInstance().getPCHContainerOperations(), Listener);
}
//===----------------------------------------------------------------------===//
@@ -598,15 +617,9 @@ void DumpTokensAction::ExecuteAction() {
void GeneratePTHAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
- if (CI.getFrontendOpts().OutputFile.empty() ||
- CI.getFrontendOpts().OutputFile == "-") {
- // FIXME: Don't fail this way.
- // FIXME: Verify that we can actually seek in the given file.
- llvm::report_fatal_error("PTH requires a seekable file for output!");
- }
- llvm::raw_fd_ostream *OS =
- CI.createDefaultOutputFile(true, getCurrentFile());
- if (!OS) return;
+ raw_pwrite_stream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS)
+ return;
CacheTokens(CI.getPreprocessor(), OS);
}
@@ -688,6 +701,7 @@ void PrintPreambleAction::ExecuteAction() {
case IK_None:
case IK_Asm:
case IK_PreprocessedC:
+ case IK_PreprocessedCuda:
case IK_PreprocessedCXX:
case IK_PreprocessedObjC:
case IK_PreprocessedObjCXX:
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
index 1869d0c..9ede674 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
@@ -18,6 +18,7 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
.Cases("S", "s", IK_Asm)
.Case("i", IK_PreprocessedC)
.Case("ii", IK_PreprocessedCXX)
+ .Case("cui", IK_PreprocessedCuda)
.Case("m", IK_ObjC)
.Case("mi", IK_PreprocessedObjC)
.Cases("mm", "M", IK_ObjCXX)
diff --git a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
index 2701194..5732e5b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -35,7 +35,7 @@ public:
OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_),
ShowDepth(ShowDepth_), MSStyle(MSStyle_) {}
- ~HeaderIncludesCallback() {
+ ~HeaderIncludesCallback() override {
if (OwnsOutputFile)
delete OutputFile;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index a518a0a..e3a17c9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -65,7 +65,7 @@ public:
/// AddSystemHeaderPrefix - Add the specified prefix to the system header
/// prefix list.
void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
- SystemHeaderPrefixes.push_back(std::make_pair(Prefix, IsSystemHeader));
+ SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
}
/// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
@@ -82,11 +82,6 @@ public:
StringRef Arch,
StringRef Version);
- /// AddMinGW64CXXPaths - Add the necessary paths to support
- /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64.
- void AddMinGW64CXXPaths(StringRef Base,
- StringRef Version);
-
// AddDefaultCIncludePaths - Add paths that should always be searched.
void AddDefaultCIncludePaths(const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts);
@@ -208,30 +203,22 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
CXXSystem, false);
}
-void InitHeaderSearch::AddMinGW64CXXPaths(StringRef Base,
- StringRef Version) {
- // Assumes Base is HeaderSearchOpts' ResourceDir
- AddPath(Base + "/../../../include/c++/" + Version,
- CXXSystem, false);
- AddPath(Base + "/../../../include/c++/" + Version + "/x86_64-w64-mingw32",
- CXXSystem, false);
- AddPath(Base + "/../../../include/c++/" + Version + "/i686-w64-mingw32",
- CXXSystem, false);
- AddPath(Base + "/../../../include/c++/" + Version + "/backward",
- CXXSystem, false);
-}
-
void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts) {
llvm::Triple::OSType os = triple.getOS();
if (HSOpts.UseStandardSystemIncludes) {
switch (os) {
+ case llvm::Triple::CloudABI:
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
case llvm::Triple::Bitrig:
+ case llvm::Triple::NaCl:
break;
+ case llvm::Triple::Win32:
+ if (triple.getEnvironment() != llvm::Triple::Cygnus)
+ break;
default:
// FIXME: temporary hack: hard-coded paths.
AddPath("/usr/local/include", System, false);
@@ -246,7 +233,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
// supplied path.
SmallString<128> P = StringRef(HSOpts.ResourceDir);
llvm::sys::path::append(P, "include");
- AddUnmappedPath(P.str(), ExternCSystem, false);
+ AddUnmappedPath(P, ExternCSystem, false);
}
// All remaining additions are for system include directories, early exit if
@@ -270,6 +257,14 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::Linux:
llvm_unreachable("Include management is handled in the driver.");
+ case llvm::Triple::CloudABI: {
+ // <sysroot>/<triple>/include
+ SmallString<128> P = StringRef(HSOpts.ResourceDir);
+ llvm::sys::path::append(P, "../../..", triple.str(), "include");
+ AddPath(P, System, false);
+ break;
+ }
+
case llvm::Triple::Haiku:
AddPath("/boot/common/include", System, false);
AddPath("/boot/develop/headers/os", System, false);
@@ -313,26 +308,6 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
AddPath("/usr/include/w32api", System, false);
break;
case llvm::Triple::GNU:
- // mingw-w64 crt include paths
- // <sysroot>/i686-w64-mingw32/include
- SmallString<128> P = StringRef(HSOpts.ResourceDir);
- llvm::sys::path::append(P, "../../../i686-w64-mingw32/include");
- AddPath(P.str(), System, false);
-
- // <sysroot>/x86_64-w64-mingw32/include
- P.resize(HSOpts.ResourceDir.size());
- llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include");
- AddPath(P.str(), System, false);
-
- // mingw.org crt include paths
- // <sysroot>/include
- P.resize(HSOpts.ResourceDir.size());
- llvm::sys::path::append(P, "../../../include");
- AddPath(P.str(), System, false);
- AddPath("/mingw/include", System, false);
-#if defined(LLVM_ON_WIN32)
- AddPath("c:/mingw/include", System, false);
-#endif
break;
}
break;
@@ -340,8 +315,15 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
break;
}
- if ( os != llvm::Triple::RTEMS )
+ switch (os) {
+ case llvm::Triple::CloudABI:
+ case llvm::Triple::RTEMS:
+ case llvm::Triple::NaCl:
+ break;
+ default:
AddPath("/usr/include", ExternCSystem, false);
+ break;
+ }
}
void InitHeaderSearch::
@@ -402,27 +384,8 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
// g++-4 / Cygwin-1.5
AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
break;
- case llvm::Triple::GNU:
- // mingw-w64 C++ include paths (i686-w64-mingw32 and x86_64-w64-mingw32)
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.1");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.2");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.3");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.0");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.1");
- AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.2");
- // mingw.org C++ include paths
-#if defined(LLVM_ON_WIN32)
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.0");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.1");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.2");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.3");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.0");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.1");
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.2");
-#endif
- break;
}
+ break;
case llvm::Triple::DragonFly:
if (llvm::sys::fs::exists("/usr/lib/gcc47"))
AddPath("/usr/include/c++/4.7", CXXSystem, false);
@@ -465,8 +428,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
return;
case llvm::Triple::Win32:
- if (triple.getEnvironment() == llvm::Triple::MSVC ||
- triple.getEnvironment() == llvm::Triple::Itanium ||
+ if (triple.getEnvironment() != llvm::Triple::Cygnus ||
triple.isOSBinFormatMachO())
return;
break;
@@ -488,7 +450,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
// Get foo/include/c++/v1
llvm::sys::path::append(P, "include", "c++", "v1");
- AddUnmappedPath(P.str(), CXXSystem, false);
+ AddUnmappedPath(P, CXXSystem, false);
}
}
// On Solaris, include the support directory for things like xlocale and
@@ -699,7 +661,7 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
// Set up the builtin include directory in the module map.
SmallString<128> P = StringRef(HSOpts.ResourceDir);
llvm::sys::path::append(P, "include");
- if (const DirectoryEntry *Dir = HS.getFileMgr().getDirectory(P.str()))
+ if (const DirectoryEntry *Dir = HS.getFileMgr().getDirectory(P))
HS.getModuleMap().setBuiltinIncludeDir(Dir);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index 3550ac2..025c8b9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -97,10 +97,11 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
/// \brief Add an implicit \#include using the original file used to generate
/// a PCH file.
static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
+ const PCHContainerOperations &PCHContainerOps,
StringRef ImplicitIncludePCH) {
std::string OriginalFile =
- ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(),
- PP.getDiagnostics());
+ ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(),
+ PCHContainerOps, PP.getDiagnostics());
if (OriginalFile.empty())
return;
@@ -133,6 +134,7 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
"4.94065645841246544176568792868221e-324",
"6.47517511943802511092443895822764655e-4966");
int Digits = PickFP(Sem, 6, 15, 18, 31, 33);
+ int DecimalDigits = PickFP(Sem, 9, 17, 21, 33, 36);
Epsilon = PickFP(Sem, "1.19209290e-7", "2.2204460492503131e-16",
"1.08420217248550443401e-19",
"4.94065645841246544176568792868221e-324",
@@ -159,6 +161,7 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
Builder.defineMacro(DefPrefix + "DENORM_MIN__", Twine(DenormMin)+Ext);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
Builder.defineMacro(DefPrefix + "DIG__", Twine(Digits));
+ Builder.defineMacro(DefPrefix + "DECIMAL_DIG__", Twine(DecimalDigits));
Builder.defineMacro(DefPrefix + "EPSILON__", Twine(Epsilon)+Ext);
Builder.defineMacro(DefPrefix + "HAS_INFINITY__");
Builder.defineMacro(DefPrefix + "HAS_QUIET_NAN__");
@@ -451,6 +454,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
}
if (LangOpts.SizedDeallocation)
Builder.defineMacro("__cpp_sized_deallocation", "201309");
+ if (LangOpts.ConceptsTS)
+ Builder.defineMacro("__cpp_experimental_concepts", "1");
}
static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -705,6 +710,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__POINTER_WIDTH__",
Twine((int)TI.getPointerWidth(0)));
+ // Define __BIGGEST_ALIGNMENT__ to be compatible with gcc.
+ Builder.defineMacro("__BIGGEST_ALIGNMENT__",
+ Twine(TI.getSuitableAlign() / TI.getCharWidth()) );
+
if (!LangOpts.CharIsSigned)
Builder.defineMacro("__CHAR_UNSIGNED__");
@@ -784,7 +793,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
if (!LangOpts.MSVCCompat) {
- if (LangOpts.GNUInline)
+ if (LangOpts.GNUInline || LangOpts.CPlusPlus)
Builder.defineMacro("__GNUC_GNU_INLINE__");
else
Builder.defineMacro("__GNUC_STDC_INLINE__");
@@ -831,8 +840,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// Macros to control C99 numerics and <float.h>
Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod()));
Builder.defineMacro("__FLT_RADIX__", "2");
- int Dig = PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36);
- Builder.defineMacro("__DECIMAL_DIG__", Twine(Dig));
+ Builder.defineMacro("__DECIMAL_DIG__", "__LDBL_DECIMAL_DIG__");
if (LangOpts.getStackProtector() == LangOptions::SSPOn)
Builder.defineMacro("__SSP__");
@@ -860,6 +868,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
"__attribute__((objc_ownership(none)))");
}
+ // On Darwin, there are __double_underscored variants of the type
+ // nullability qualifiers.
+ if (TI.getTriple().isOSDarwin()) {
+ Builder.defineMacro("__nonnull", "_Nonnull");
+ Builder.defineMacro("__null_unspecified", "_Null_unspecified");
+ Builder.defineMacro("__nullable", "_Nullable");
+ }
+
// OpenMP definition
if (LangOpts.OpenMP) {
// OpenMP 2.2:
@@ -884,9 +900,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
-void clang::InitializePreprocessor(Preprocessor &PP,
- const PreprocessorOptions &InitOpts,
- const FrontendOptions &FEOpts) {
+void clang::InitializePreprocessor(
+ Preprocessor &PP, const PreprocessorOptions &InitOpts,
+ const PCHContainerOperations &PCHContainerOps,
+ const FrontendOptions &FEOpts) {
const LangOptions &LangOpts = PP.getLangOpts();
std::string PredefineBuffer;
PredefineBuffer.reserve(4080);
@@ -945,7 +962,8 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// Process -include-pch/-include-pth directives.
if (!InitOpts.ImplicitPCHInclude.empty())
- AddImplicitIncludePCH(Builder, PP, InitOpts.ImplicitPCHInclude);
+ AddImplicitIncludePCH(Builder, PP, PCHContainerOps,
+ InitOpts.ImplicitPCHInclude);
if (!InitOpts.ImplicitPTHInclude.empty())
AddImplicitIncludePTH(Builder, PP, InitOpts.ImplicitPTHInclude);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
index 62865e9..67852dc 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
@@ -77,10 +77,10 @@ std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
/*IgnoreExisting=*/true))
return EC;
- if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str()))
+ if (std::error_code EC = fs::copy_file(AbsoluteSrc, Dest))
return EC;
// Use the absolute path under the root for the file mapping.
- Collector.addFileMapping(AbsoluteSrc.str(), Dest.str());
+ Collector.addFileMapping(AbsoluteSrc, Dest);
return std::error_code();
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
index 0198828..91ee100 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -33,13 +33,16 @@ public:
void ReaderInitialized(ASTReader *Reader) override;
void IdentifierRead(serialization::IdentID ID,
IdentifierInfo *II) override;
+ void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
void TypeRead(serialization::TypeIdx Idx, QualType T) override;
void DeclRead(serialization::DeclID ID, const Decl *D) override;
void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
void MacroDefinitionRead(serialization::PreprocessedEntityID,
- MacroDefinition *MD) override;
+ MacroDefinitionRecord *MD) override;
+ void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
+
private:
- std::vector<ASTDeserializationListener*> Listeners;
+ std::vector<ASTDeserializationListener *> Listeners;
};
MultiplexASTDeserializationListener::MultiplexASTDeserializationListener(
@@ -59,6 +62,12 @@ void MultiplexASTDeserializationListener::IdentifierRead(
Listeners[i]->IdentifierRead(ID, II);
}
+void MultiplexASTDeserializationListener::MacroRead(
+ serialization::MacroID ID, MacroInfo *MI) {
+ for (auto &Listener : Listeners)
+ Listener->MacroRead(ID, MI);
+}
+
void MultiplexASTDeserializationListener::TypeRead(
serialization::TypeIdx Idx, QualType T) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
@@ -78,11 +87,17 @@ void MultiplexASTDeserializationListener::SelectorRead(
}
void MultiplexASTDeserializationListener::MacroDefinitionRead(
- serialization::PreprocessedEntityID ID, MacroDefinition *MD) {
+ serialization::PreprocessedEntityID ID, MacroDefinitionRecord *MD) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->MacroDefinitionRead(ID, MD);
}
+void MultiplexASTDeserializationListener::ModuleRead(
+ serialization::SubmoduleID ID, Module *Mod) {
+ for (auto &Listener : Listeners)
+ Listener->ModuleRead(ID, Mod);
+}
+
// This ASTMutationListener forwards its notifications to a set of
// child listeners.
class MultiplexASTMutationListener : public ASTMutationListener {
@@ -98,16 +113,23 @@ public:
const VarTemplateSpecializationDecl *D) override;
void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) override;
+ void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
+ void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
+ void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
const ObjCPropertyDecl *OrigProp,
const ObjCCategoryDecl *ClassExt) override;
void DeclarationMarkedUsed(const Decl *D) override;
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
+ void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
+ void AddedAttributeToRecord(const Attr *Attr,
+ const RecordDecl *Record) override;
private:
std::vector<ASTMutationListener*> Listeners;
@@ -149,11 +171,21 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
}
+void MultiplexASTMutationListener::ResolvedExceptionSpec(
+ const FunctionDecl *FD) {
+ for (auto &Listener : Listeners)
+ Listener->ResolvedExceptionSpec(FD);
+}
void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
QualType ReturnType) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeducedReturnType(FD, ReturnType);
}
+void MultiplexASTMutationListener::ResolvedOperatorDelete(
+ const CXXDestructorDecl *DD, const FunctionDecl *Delete) {
+ for (auto *L : Listeners)
+ L->ResolvedOperatorDelete(DD, Delete);
+}
void MultiplexASTMutationListener::CompletedImplicitDefinition(
const FunctionDecl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
@@ -170,6 +202,11 @@ void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD);
}
+void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
+ const FunctionDecl *D) {
+ for (auto &Listener : Listeners)
+ Listener->FunctionDefinitionInstantiated(D);
+}
void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension(
const ObjCPropertyDecl *Prop,
const ObjCPropertyDecl *OrigProp,
@@ -186,6 +223,18 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
}
+void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D,
+ Module *M) {
+ for (auto *L : Listeners)
+ L->RedefinedHiddenDefinition(D, M);
+}
+
+void MultiplexASTMutationListener::AddedAttributeToRecord(
+ const Attr *Attr,
+ const RecordDecl *Record) {
+ for (auto *L : Listeners)
+ L->AddedAttributeToRecord(Attr, Record);
+}
} // end namespace clang
@@ -292,10 +341,9 @@ void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
Consumer->CompleteTentativeDefinition(D);
}
-void MultiplexConsumer::HandleVTable(
- CXXRecordDecl *RD, bool DefinitionRequired) {
+void MultiplexConsumer::HandleVTable(CXXRecordDecl *RD) {
for (auto &Consumer : Consumers)
- Consumer->HandleVTable(RD, DefinitionRequired);
+ Consumer->HandleVTable(RD);
}
ASTMutationListener *MultiplexConsumer::GetASTMutationListener() {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
new file mode 100644
index 0000000..c749bb5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
@@ -0,0 +1,68 @@
+//===--- Frontend/PCHContainerOperations.cpp - PCH Containers ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines PCHContainerOperations and RawPCHContainerOperation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/AST/ASTConsumer.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Lex/ModuleLoader.h"
+using namespace clang;
+
+namespace {
+
+/// \brief A PCHContainerGenerator that writes out the PCH to a flat file.
+class PCHContainerGenerator : public ASTConsumer {
+ std::shared_ptr<PCHBuffer> Buffer;
+ raw_pwrite_stream *OS;
+
+public:
+ PCHContainerGenerator(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)
+ : Buffer(Buffer), OS(OS) {}
+
+ virtual ~PCHContainerGenerator() {}
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ if (Buffer->IsComplete) {
+ // Make sure it hits disk now.
+ *OS << Buffer->Data;
+ OS->flush();
+ }
+ // Free the space of the temporary buffer.
+ llvm::SmallVector<char, 0> Empty;
+ Buffer->Data = std::move(Empty);
+ }
+};
+}
+
+std::unique_ptr<ASTConsumer>
+RawPCHContainerOperations::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 RawPCHContainerOperations::ExtractPCH(
+ llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
+ StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
+ (const unsigned char *)Buffer.getBufferEnd());
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 7c1d9a5..a58c935 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -64,12 +64,11 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
OS << ' ';
SmallString<128> SpellingBuffer;
- for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
- I != E; ++I) {
- if (I->hasLeadingSpace())
+ for (const auto &T : MI.tokens()) {
+ if (T.hasLeadingSpace())
OS << ' ';
- OS << PP.getSpelling(*I, SpellingBuffer);
+ OS << PP.getSpelling(T, SpellingBuffer);
}
}
@@ -94,14 +93,14 @@ private:
bool Initialized;
bool DisableLineMarkers;
bool DumpDefines;
- bool UseLineDirective;
+ bool UseLineDirectives;
bool IsFirstFileEntered;
public:
- PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os,
- bool lineMarkers, bool defines)
- : PP(pp), SM(PP.getSourceManager()),
- ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
- DumpDefines(defines) {
+ PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
+ bool defines, bool UseLineDirectives)
+ : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
+ DisableLineMarkers(lineMarkers), DumpDefines(defines),
+ UseLineDirectives(UseLineDirectives) {
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
@@ -109,9 +108,6 @@ public:
FileType = SrcMgr::C_User;
Initialized = false;
IsFirstFileEntered = false;
-
- // If we're in microsoft mode, use normal #line instead of line markers.
- UseLineDirective = PP.getLangOpts().MicrosoftExt;
}
void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
@@ -132,7 +128,7 @@ public:
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
const Module *Imported) override;
- void Ident(SourceLocation Loc, const std::string &str) override;
+ void Ident(SourceLocation Loc, StringRef str) override;
void PragmaMessage(SourceLocation Loc, StringRef Namespace,
PragmaMessageKind Kind, StringRef Str) override;
void PragmaDebug(SourceLocation Loc, StringRef DebugType) override;
@@ -173,7 +169,7 @@ public:
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
void MacroUndefined(const Token &MacroNameTok,
- const MacroDirective *MD) override;
+ const MacroDefinition &MD) override;
};
} // end anonymous namespace
@@ -183,7 +179,7 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
// Emit #line directives or GNU line markers depending on what mode we're in.
- if (UseLineDirective) {
+ if (UseLineDirectives) {
OS << "#line" << ' ' << LineNo << ' ' << '"';
OS.write_escaped(CurFilename);
OS << '"';
@@ -341,11 +337,11 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
/// Ident - Handle #ident directives when read by the preprocessor.
///
-void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
+void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) {
MoveToLine(Loc);
OS.write("#ident ", strlen("#ident "));
- OS.write(&S[0], S.size());
+ OS.write(S.begin(), S.size());
EmittedTokensOnThisLine = true;
}
@@ -364,7 +360,7 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
}
void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
- const MacroDirective *MD) {
+ const MacroDefinition &MD) {
// Only print out macro definitions in -dD mode.
if (!DumpDefines) return;
@@ -566,8 +562,13 @@ struct UnknownPragmaHandler : public PragmaHandler {
const char *Prefix;
PrintPPOutputPPCallbacks *Callbacks;
- UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
- : Prefix(prefix), Callbacks(callbacks) {}
+ // Set to true if tokens should be expanded
+ bool ShouldExpandTokens;
+
+ UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks,
+ bool RequireTokenExpansion)
+ : Prefix(prefix), Callbacks(callbacks),
+ ShouldExpandTokens(RequireTokenExpansion) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &PragmaTok) override {
// Figure out what line we went to and insert the appropriate number of
@@ -575,16 +576,24 @@ struct UnknownPragmaHandler : public PragmaHandler {
Callbacks->startNewLineIfNeeded();
Callbacks->MoveToLine(PragmaTok.getLocation());
Callbacks->OS.write(Prefix, strlen(Prefix));
+
+ Token PrevToken;
+ Token PrevPrevToken;
+ PrevToken.startToken();
+ PrevPrevToken.startToken();
+
// Read and print all of the pragma tokens.
while (PragmaTok.isNot(tok::eod)) {
- if (PragmaTok.hasLeadingSpace())
+ if (PragmaTok.hasLeadingSpace() ||
+ Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok))
Callbacks->OS << ' ';
std::string TokSpell = PP.getSpelling(PragmaTok);
Callbacks->OS.write(&TokSpell[0], TokSpell.size());
- // Expand macros in pragmas with -fms-extensions. The assumption is that
- // the majority of pragmas in such a file will be Microsoft pragmas.
- if (PP.getLangOpts().MicrosoftExt)
+ PrevPrevToken = PrevToken;
+ PrevToken = PragmaTok;
+
+ if (ShouldExpandTokens)
PP.Lex(PragmaTok);
else
PP.LexUnexpandedToken(PragmaTok);
@@ -689,8 +698,9 @@ static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) {
SmallVector<id_macro_pair, 128> MacrosByID;
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
- if (I->first->hasMacroDefinition())
- MacrosByID.push_back(id_macro_pair(I->first, I->second->getMacroInfo()));
+ auto *MD = I->second.getLatest();
+ if (MD && MD->isDefined())
+ MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo()));
}
llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
@@ -719,13 +729,31 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
// to -C or -CC.
PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
- PrintPPOutputPPCallbacks *Callbacks =
- new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
- Opts.ShowMacros);
- PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks));
- PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks));
- PP.AddPragmaHandler("clang",
- new UnknownPragmaHandler("#pragma clang", Callbacks));
+ PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(
+ PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.UseLineDirectives);
+
+ // Expand macros in pragmas with -fms-extensions. The assumption is that
+ // the majority of pragmas in such a file will be Microsoft pragmas.
+ PP.AddPragmaHandler(new UnknownPragmaHandler(
+ "#pragma", Callbacks,
+ /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt));
+ PP.AddPragmaHandler(
+ "GCC", new UnknownPragmaHandler(
+ "#pragma GCC", Callbacks,
+ /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt));
+ PP.AddPragmaHandler(
+ "clang", new UnknownPragmaHandler(
+ "#pragma clang", Callbacks,
+ /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt));
+
+ // The tokens after pragma omp need to be expanded.
+ //
+ // OpenMP [2.1, Directive format]
+ // Preprocessing tokens following the #pragma omp are subject to macro
+ // replacement.
+ PP.AddPragmaHandler("omp",
+ new UnknownPragmaHandler("#pragma omp", Callbacks,
+ /*RequireTokenExpansion=*/true));
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
index a3e14f9..dc787ac 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FixItRewriter.cpp
@@ -81,6 +81,13 @@ bool FixItRewriter::WriteFixedFiles(
RewritesReceiver Rec(Rewrite);
Editor.applyRewrites(Rec);
+ if (FixItOpts->InPlace) {
+ // Overwriting open files on Windows is tricky, but the rewriter can do it
+ // for us.
+ Rewrite.overwriteChangedFiles();
+ return false;
+ }
+
for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
int fd;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 1b5eb28..dbc661b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -48,9 +48,10 @@ FixItAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
namespace {
class FixItRewriteInPlace : public FixItOptions {
public:
+ FixItRewriteInPlace() { InPlace = true; }
+
std::string RewriteFilename(const std::string &Filename, int &fd) override {
- fd = -1;
- return Filename;
+ llvm_unreachable("don't call RewriteFilename for inplace rewrites");
}
};
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
index 1400557..08d6cf1 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -29,13 +29,11 @@ namespace {
class InclusionRewriter : public PPCallbacks {
/// Information about which #includes were actually performed,
/// created by preprocessor callbacks.
- struct FileChange {
- const Module *Mod;
- SourceLocation From;
+ struct IncludedFile {
FileID Id;
SrcMgr::CharacteristicKind FileType;
- FileChange(SourceLocation From, const Module *Mod) : Mod(Mod), From(From) {
- }
+ IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType)
+ : Id(Id), FileType(FileType) {}
};
Preprocessor &PP; ///< Used to find inclusion directives.
SourceManager &SM; ///< Used to read and manage source files.
@@ -43,14 +41,17 @@ class InclusionRewriter : public PPCallbacks {
StringRef MainEOL; ///< The line ending marker to use.
const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines.
bool ShowLineMarkers; ///< Show #line markers.
- bool UseLineDirective; ///< Use of line directives or line markers.
- typedef std::map<unsigned, FileChange> FileChangeMap;
- FileChangeMap FileChanges; ///< Tracks which files were included where.
- /// Used transitively for building up the FileChanges mapping over the
+ bool UseLineDirectives; ///< Use of line directives or line markers.
+ /// Tracks where inclusions that change the file are found.
+ std::map<unsigned, IncludedFile> FileIncludes;
+ /// Tracks where inclusions that import modules are found.
+ std::map<unsigned, const Module *> ModuleIncludes;
+ /// Used transitively for building up the FileIncludes mapping over the
/// various \c PPCallbacks callbacks.
- FileChangeMap::iterator LastInsertedFileChange;
+ SourceLocation LastInclusionLocation;
public:
- InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers);
+ InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers,
+ bool UseLineDirectives);
bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
PredefinesBuffer = Buf;
@@ -60,7 +61,7 @@ private:
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override;
- void FileSkipped(const FileEntry &ParentFile, const Token &FilenameTok,
+ void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok,
SrcMgr::CharacteristicKind FileType) override;
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
@@ -81,7 +82,8 @@ private:
bool HandleHasInclude(FileID FileId, Lexer &RawLex,
const DirectoryLookup *Lookup, Token &Tok,
bool &FileExists);
- const FileChange *FindFileChangeLocation(SourceLocation Loc) const;
+ const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
+ const Module *FindModuleAtLocation(SourceLocation Loc) const;
StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
};
@@ -89,13 +91,12 @@ private:
/// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
- bool ShowLineMarkers)
+ bool ShowLineMarkers,
+ bool UseLineDirectives)
: PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers),
- LastInsertedFileChange(FileChanges.end()) {
- // If we're in microsoft mode, use normal #line instead of line markers.
- UseLineDirective = PP.getLangOpts().MicrosoftExt;
-}
+ UseLineDirectives(UseLineDirectives),
+ LastInclusionLocation(SourceLocation()) {}
/// Write appropriate line information as either #line directives or GNU line
/// markers depending on what mode we're in, including the \p Filename and
@@ -106,7 +107,7 @@ void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
StringRef Extra) {
if (!ShowLineMarkers)
return;
- if (UseLineDirective) {
+ if (UseLineDirectives) {
OS << "#line" << ' ' << Line << ' ' << '"';
OS.write_escaped(Filename);
OS << '"';
@@ -143,23 +144,25 @@ void InclusionRewriter::FileChanged(SourceLocation Loc,
FileID) {
if (Reason != EnterFile)
return;
- if (LastInsertedFileChange == FileChanges.end())
+ if (LastInclusionLocation.isInvalid())
// we didn't reach this file (eg: the main file) via an inclusion directive
return;
- LastInsertedFileChange->second.Id = FullSourceLoc(Loc, SM).getFileID();
- LastInsertedFileChange->second.FileType = NewFileType;
- LastInsertedFileChange = FileChanges.end();
+ FileID Id = FullSourceLoc(Loc, SM).getFileID();
+ auto P = FileIncludes.insert(std::make_pair(
+ LastInclusionLocation.getRawEncoding(), IncludedFile(Id, NewFileType)));
+ (void)P;
+ assert(P.second && "Unexpected revisitation of the same include directive");
+ LastInclusionLocation = SourceLocation();
}
/// Called whenever an inclusion is skipped due to canonical header protection
/// macros.
-void InclusionRewriter::FileSkipped(const FileEntry &/*ParentFile*/,
+void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/,
const Token &/*FilenameTok*/,
SrcMgr::CharacteristicKind /*FileType*/) {
- assert(LastInsertedFileChange != FileChanges.end() && "A file, that wasn't "
- "found via an inclusion directive, was skipped");
- FileChanges.erase(LastInsertedFileChange);
- LastInsertedFileChange = FileChanges.end();
+ assert(!LastInclusionLocation.isInvalid() &&
+ "A file, that wasn't found via an inclusion directive, was skipped");
+ LastInclusionLocation = SourceLocation();
}
/// This should be called whenever the preprocessor encounters include
@@ -176,25 +179,38 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
StringRef /*SearchPath*/,
StringRef /*RelativePath*/,
const Module *Imported) {
- assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
- "directive was found before the previous one was processed");
- std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
- std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc, Imported)));
- assert(p.second && "Unexpected revisitation of the same include directive");
- if (!Imported)
- LastInsertedFileChange = p.first;
+ assert(LastInclusionLocation.isInvalid() &&
+ "Another inclusion directive was found before the previous one "
+ "was processed");
+ if (Imported) {
+ auto P = ModuleIncludes.insert(
+ std::make_pair(HashLoc.getRawEncoding(), Imported));
+ (void)P;
+ assert(P.second && "Unexpected revisitation of the same include directive");
+ } else
+ LastInclusionLocation = HashLoc;
}
/// Simple lookup for a SourceLocation (specifically one denoting the hash in
/// an inclusion directive) in the map of inclusion information, FileChanges.
-const InclusionRewriter::FileChange *
-InclusionRewriter::FindFileChangeLocation(SourceLocation Loc) const {
- FileChangeMap::const_iterator I = FileChanges.find(Loc.getRawEncoding());
- if (I != FileChanges.end())
+const InclusionRewriter::IncludedFile *
+InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const {
+ const auto I = FileIncludes.find(Loc.getRawEncoding());
+ if (I != FileIncludes.end())
return &I->second;
return nullptr;
}
+/// Simple lookup for a SourceLocation (specifically one denoting the hash in
+/// an inclusion directive) in the map of module inclusion information.
+const Module *
+InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const {
+ const auto I = ModuleIncludes.find(Loc.getRawEncoding());
+ if (I != ModuleIncludes.end())
+ return I->second;
+ return nullptr;
+}
+
/// Detect the likely line ending style of \p FromFile by examining the first
/// newline found within it.
static StringRef DetectEOL(const MemoryBuffer &FromFile) {
@@ -388,8 +404,7 @@ bool InclusionRewriter::Process(FileID FileId,
{
bool Invalid;
const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
- if (Invalid) // invalid inclusion
- return false;
+ assert(!Invalid && "Attempting to process invalid inclusion");
const char *FileName = FromFile.getBufferIdentifier();
Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
RawLex.SetCommentRetentionState(false);
@@ -433,13 +448,12 @@ bool InclusionRewriter::Process(FileID FileId,
if (FileId != PP.getPredefinesFileID())
WriteLineInfo(FileName, Line - 1, FileType, "");
StringRef LineInfoExtra;
- if (const FileChange *Change = FindFileChangeLocation(
- HashToken.getLocation())) {
- if (Change->Mod) {
- WriteImplicitModuleImport(Change->Mod);
-
- // else now include and recursively process the file
- } else if (Process(Change->Id, Change->FileType)) {
+ SourceLocation Loc = HashToken.getLocation();
+ if (const Module *Mod = FindModuleAtLocation(Loc))
+ WriteImplicitModuleImport(Mod);
+ else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
+ // include and recursively process the file
+ if (Process(Inc->Id, Inc->FileType)) {
// and set lineinfo back to this file, if the nested one was
// actually included
// `2' indicates returning to a file (after having included
@@ -561,8 +575,8 @@ bool InclusionRewriter::Process(FileID FileId,
void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
const PreprocessorOutputOptions &Opts) {
SourceManager &SM = PP.getSourceManager();
- InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS,
- Opts.ShowLineMarkers);
+ InclusionRewriter *Rewrite = new InclusionRewriter(
+ PP, *OS, Opts.ShowLineMarkers, Opts.UseLineDirectives);
Rewrite->detectMainFileEOL();
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Rewrite));
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 47f8189..2902ba7 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -243,8 +243,8 @@ namespace {
RewriteModernObjC(std::string inFile, raw_ostream *OS,
DiagnosticsEngine &D, const LangOptions &LOpts,
bool silenceMacroWarn, bool LineInfo);
-
- ~RewriteModernObjC() {}
+
+ ~RewriteModernObjC() override {}
void HandleTranslationUnit(ASTContext &C) override;
@@ -889,9 +889,9 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
IvarT, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
@@ -1932,9 +1932,9 @@ Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S)
void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
{
// Perform a bottom up traversal of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI)
- WarnAboutReturnGotoStmts(*CI);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt)
+ WarnAboutReturnGotoStmts(SubStmt);
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
Diags.Report(Context->getFullLoc(S->getLocStart()),
@@ -2689,7 +2689,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
MsgExprs.push_back(subExpr);
SmallVector<QualType, 4> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto PI : BoxingMethod->parameters())
ArgTypes.push_back(PI->getType());
@@ -2767,11 +2767,9 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ArrayLiteralME =
- new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ArrayLiteralME = new (Context)
+ MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * ArrayLiteralObjects =
NoTypeInfoCStyleCastExpr(Context,
@@ -2818,7 +2816,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
SmallVector<QualType, 4> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto *PI : ArrayMethod->params())
ArgTypes.push_back(PI->getType());
@@ -2904,11 +2902,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *DictLiteralValueME =
- new (Context) MemberExpr(NSValueCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *DictLiteralValueME = new (Context)
+ MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * DictValueObjects =
NoTypeInfoCStyleCastExpr(Context,
@@ -2919,13 +2915,11 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
Expr *NSKeyCallExpr =
new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
NSDictFType, VK_LValue, SourceLocation());
-
- MemberExpr *DictLiteralKeyME =
- new (Context) MemberExpr(NSKeyCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
-
+
+ MemberExpr *DictLiteralKeyME = new (Context)
+ MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+
CStyleCastExpr * DictKeyObjects =
NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
@@ -2975,7 +2969,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
SmallVector<QualType, 8> ArgTypes;
- ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCClassType());
ArgTypes.push_back(Context->getObjCSelType());
for (const auto *PI : DictMethod->params()) {
QualType T = PI->getType();
@@ -3234,9 +3228,9 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
returnType, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
- FieldD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
+ FieldD->getType(), VK_LValue, OK_Ordinary);
return ME;
}
@@ -4555,12 +4549,12 @@ void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
}
void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
GetBlockDeclRefExprs(CBE->getBody());
else
- GetBlockDeclRefExprs(*CI);
+ GetBlockDeclRefExprs(SubStmt);
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
@@ -4575,19 +4569,16 @@ void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
GetInnerBlockDeclRefExprs(CBE->getBody(),
InnerBlockDeclRefs,
InnerContexts);
}
else
- GetInnerBlockDeclRefExprs(*CI,
- InnerBlockDeclRefs,
- InnerContexts);
-
+ GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
@@ -4732,11 +4723,10 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME =
+ new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
-
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
@@ -4781,10 +4771,9 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
- FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
@@ -4792,11 +4781,10 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-
-
-
+ ME =
+ new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
DeclRefExp->getExprLoc(),
@@ -5573,12 +5561,11 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
SourceRange OrigStmtRange = S->getSourceRange();
// Perform a bottom up rewrite of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- Stmt *childStmt = (*CI);
+ for (Stmt *&childStmt : S->children())
+ if (childStmt) {
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
if (newStmt) {
- *CI = newStmt;
+ childStmt = newStmt;
}
}
@@ -7694,9 +7681,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
IvarT, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
@@ -7723,9 +7710,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
D->getType(), nullptr,
/*BitWidth=*/D->getBitWidth(),
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, /*isArrow*/false, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
+ SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 5196810..204820b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -193,7 +193,7 @@ namespace {
DiagnosticsEngine &D, const LangOptions &LOpts,
bool silenceMacroWarn);
- ~RewriteObjC() {}
+ ~RewriteObjC() override {}
void HandleTranslationUnit(ASTContext &C) override;
@@ -511,8 +511,8 @@ namespace {
bool silenceMacroWarn) : RewriteObjC(inFile, OS,
D, LOpts,
silenceMacroWarn) {}
-
- ~RewriteObjCFragileABI() {}
+
+ ~RewriteObjCFragileABI() override {}
void Initialize(ASTContext &context) override;
// Rewriting metadata
@@ -1712,9 +1712,9 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
{
// Perform a bottom up traversal of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI)
- WarnAboutReturnGotoStmts(*CI);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt)
+ WarnAboutReturnGotoStmts(SubStmt);
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
Diags.Report(Context->getFullLoc(S->getLocStart()),
@@ -1726,9 +1726,9 @@ void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
{
// Perform a bottom up traversal of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI)
- HasReturnStmts(*CI, hasReturns);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt)
+ HasReturnStmts(SubStmt, hasReturns);
if (isa<ReturnStmt>(S))
hasReturns = true;
@@ -1737,9 +1737,9 @@ void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
// Perform a bottom up traversal of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- RewriteTryReturnStmts(*CI);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ RewriteTryReturnStmts(SubStmt);
}
if (isa<ReturnStmt>(S)) {
SourceLocation startLoc = S->getLocStart();
@@ -1760,9 +1760,9 @@ void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
// Perform a bottom up traversal of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- RewriteSyncReturnStmts(*CI, syncExitBuf);
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ RewriteSyncReturnStmts(SubStmt, syncExitBuf);
}
if (isa<ReturnStmt>(S)) {
SourceLocation startLoc = S->getLocStart();
@@ -3663,12 +3663,12 @@ void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
}
void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
GetBlockDeclRefExprs(CBE->getBody());
else
- GetBlockDeclRefExprs(*CI);
+ GetBlockDeclRefExprs(SubStmt);
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
@@ -3683,19 +3683,16 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
GetInnerBlockDeclRefExprs(CBE->getBody(),
InnerBlockDeclRefs,
InnerContexts);
}
else
- GetInnerBlockDeclRefExprs(*CI,
- InnerBlockDeclRefs,
- InnerContexts);
-
+ GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
@@ -3821,11 +3818,10 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME =
+ new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
-
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
@@ -3870,10 +3866,9 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
- FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
@@ -3881,11 +3876,10 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-
-
-
+ ME =
+ new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
DeclRefExp->getExprLoc(),
@@ -4614,12 +4608,11 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
SourceRange OrigStmtRange = S->getSourceRange();
// Perform a bottom up rewrite of all children.
- for (Stmt::child_range CI = S->children(); CI; ++CI)
- if (*CI) {
- Stmt *childStmt = (*CI);
+ for (Stmt *&childStmt : S->children())
+ if (childStmt) {
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
if (newStmt) {
- *CI = newStmt;
+ childStmt = newStmt;
}
}
@@ -5880,10 +5873,9 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
castExpr);
if (IV->isFreeIvar() &&
declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) {
- MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
- IV->getLocation(),
- D->getType(),
- VK_LValue, OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), D, IV->getLocation(),
+ D->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
} else {
IV->setBase(PE);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index f701f72..d31b12e 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -20,6 +20,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -60,8 +61,8 @@ public:
DiagnosticOptions *DiagOpts)
: DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
- virtual ~SDiagsRenderer() {}
-
+ ~SDiagsRenderer() override {}
+
protected:
void emitDiagnosticMessage(SourceLocation Loc,
PresumedLoc PLoc,
@@ -157,7 +158,7 @@ public:
EmitPreamble();
}
- ~SDiagsWriter() {}
+ ~SDiagsWriter() override {}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;
@@ -631,7 +632,7 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
"Unexpected diagnostic with valid location outside of a source file");
SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
- State->diagBuf.str(),
+ State->diagBuf,
Info.getRanges(),
Info.getFixItHints(),
&Info.getSourceManager(),
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
index bbc9914..aaf17a9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
@@ -799,18 +799,18 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
OS << PLoc.getFilename();
switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang: OS << ':' << LineNo; break;
- case DiagnosticOptions::Msvc: OS << '(' << LineNo; break;
+ case DiagnosticOptions::MSVC: OS << '(' << LineNo; break;
case DiagnosticOptions::Vi: OS << " +" << LineNo; break;
}
if (DiagOpts->ShowColumn)
// Compute the column number.
if (unsigned ColNo = PLoc.getColumn()) {
- if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) {
+ if (DiagOpts->getFormat() == DiagnosticOptions::MSVC) {
OS << ',';
// Visual Studio 2010 or earlier expects column number to be off by one
if (LangOpts.MSCompatibilityVersion &&
- LangOpts.MSCompatibilityVersion < 170000000)
+ !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2012))
ColNo--;
} else
OS << ':';
@@ -819,7 +819,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang:
case DiagnosticOptions::Vi: OS << ':'; break;
- case DiagnosticOptions::Msvc: OS << ") : "; break;
+ case DiagnosticOptions::MSVC: OS << ") : "; break;
}
if (DiagOpts->ShowSourceRanges && !Ranges.empty()) {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
index 9c6bebb..d49e983 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -30,17 +30,17 @@ void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level,
default: llvm_unreachable(
"Diagnostic not handled during diagnostic buffering!");
case DiagnosticsEngine::Note:
- Notes.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ Notes.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Warning:
- Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ Warnings.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Remark:
- Remarks.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ Remarks.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
- Errors.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ Errors.emplace_back(Info.getLocation(), Buf.str());
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 3ff6b18..55df936 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -58,9 +58,9 @@ public:
/// \brief Hook into the preprocessor and update the list of parsed
/// files when the preprocessor indicates a new file is entered.
- virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
- SrcMgr::CharacteristicKind FileType,
- FileID PrevFID) {
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
VerifyDiagnosticConsumer::IsParsed);
}
@@ -691,7 +691,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const char *Label,
DirectiveList &Left,
const_diag_iterator d2_begin,
- const_diag_iterator d2_end) {
+ const_diag_iterator d2_end,
+ bool IgnoreUnexpected) {
std::vector<Directive *> LeftOnly;
DiagList Right(d2_begin, d2_end);
@@ -727,7 +728,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
}
// Now all that's left in Right are those that were not matched.
unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);
- num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
+ if (!IgnoreUnexpected)
+ num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
return num;
}
@@ -745,21 +747,28 @@ static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
// Seen \ Expected - set seen but not expected
unsigned NumProblems = 0;
+ const DiagnosticLevelMask DiagMask =
+ Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
+
// See if there are error mismatches.
NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
- Buffer.err_begin(), Buffer.err_end());
+ Buffer.err_begin(), Buffer.err_end(),
+ bool(DiagnosticLevelMask::Error & DiagMask));
// See if there are warning mismatches.
NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
- Buffer.warn_begin(), Buffer.warn_end());
+ Buffer.warn_begin(), Buffer.warn_end(),
+ bool(DiagnosticLevelMask::Warning & DiagMask));
// See if there are remark mismatches.
NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks,
- Buffer.remark_begin(), Buffer.remark_end());
+ Buffer.remark_begin(), Buffer.remark_end(),
+ bool(DiagnosticLevelMask::Remark & DiagMask));
// See if there are note mismatches.
NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
- Buffer.note_begin(), Buffer.note_end());
+ Buffer.note_begin(), Buffer.note_end(),
+ bool(DiagnosticLevelMask::Note & DiagMask));
return NumProblems;
}
@@ -854,12 +863,20 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
// Check that the expected diagnostics occurred.
NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
} else {
- NumErrors += (PrintUnexpected(Diags, nullptr, Buffer->err_begin(),
- Buffer->err_end(), "error") +
- PrintUnexpected(Diags, nullptr, Buffer->warn_begin(),
- Buffer->warn_end(), "warn") +
- PrintUnexpected(Diags, nullptr, Buffer->note_begin(),
- Buffer->note_end(), "note"));
+ const DiagnosticLevelMask DiagMask =
+ ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
+ if (bool(DiagnosticLevelMask::Error & DiagMask))
+ NumErrors += PrintUnexpected(Diags, nullptr, Buffer->err_begin(),
+ Buffer->err_end(), "error");
+ if (bool(DiagnosticLevelMask::Warning & DiagMask))
+ NumErrors += PrintUnexpected(Diags, nullptr, Buffer->warn_begin(),
+ Buffer->warn_end(), "warn");
+ if (bool(DiagnosticLevelMask::Remark & DiagMask))
+ NumErrors += PrintUnexpected(Diags, nullptr, Buffer->remark_begin(),
+ Buffer->remark_end(), "remark");
+ if (bool(DiagnosticLevelMask::Note & DiagMask))
+ NumErrors += PrintUnexpected(Diags, nullptr, Buffer->note_begin(),
+ Buffer->note_end(), "note");
}
Diags.setClient(CurClient, Owner.release() != nullptr);
diff --git a/contrib/llvm/tools/clang/lib/Headers/Intrin.h b/contrib/llvm/tools/clang/lib/Headers/Intrin.h
index 84bc430..24b3eae 100644
--- a/contrib/llvm/tools/clang/lib/Headers/Intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/Intrin.h
@@ -39,6 +39,9 @@
#include <setjmp.h>
#endif
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -177,8 +180,6 @@ unsigned long __cdecl _byteswap_ulong(unsigned long);
unsigned short __cdecl _byteswap_ushort(unsigned short);
void __cdecl _disable(void);
void __cdecl _enable(void);
-void __cdecl _fxrstor(void const *);
-void __cdecl _fxsave(void *);
long _InterlockedAddLargeStatistic(__int64 volatile *_Addend, long _Value);
static __inline__
long _InterlockedAnd(long volatile *_Value, long _Mask);
@@ -289,6 +290,7 @@ void _WriteBarrier(void);
unsigned __int32 xbegin(void);
void _xend(void);
static __inline__
+#define _XCR_XFEATURE_ENABLED_MASK 0
unsigned __int64 __cdecl _xgetbv(unsigned int);
void __cdecl _xrstor(void const *, unsigned __int64);
void __cdecl _xsave(void *, unsigned __int64);
@@ -354,8 +356,6 @@ unsigned char _bittestandreset64(__int64 *, __int64);
static __inline__
unsigned char _bittestandset64(__int64 *, __int64);
unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64);
-void __cdecl _fxrstor64(void const *);
-void __cdecl _fxsave64(void *);
long _InterlockedAnd_np(long volatile *_Value, long _Mask);
short _InterlockedAnd16_np(short volatile *_Value, short _Mask);
__int64 _InterlockedAnd64_np(__int64 volatile *_Value, __int64 _Mask);
@@ -420,7 +420,7 @@ unsigned __int64 _shrx_u64(unsigned __int64, unsigned int);
* Multiply two 64-bit integers and obtain a 64-bit result.
* The low-half is returned directly and the high half is in an out parameter.
*/
-static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
_umul128(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand,
unsigned __int64 *_HighProduct) {
unsigned __int128 _FullProduct =
@@ -428,7 +428,7 @@ _umul128(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand,
*_HighProduct = _FullProduct >> 64;
return _FullProduct;
}
-static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__umulh(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand) {
unsigned __int128 _FullProduct =
(unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand;
@@ -443,54 +443,54 @@ void __cdecl _xsaveopt64(void *, unsigned __int64);
/*----------------------------------------------------------------------------*\
|* Bit Twiddling
\*----------------------------------------------------------------------------*/
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_rotl8(unsigned char _Value, unsigned char _Shift) {
_Shift &= 0x7;
return _Shift ? (_Value << _Shift) | (_Value >> (8 - _Shift)) : _Value;
}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_rotr8(unsigned char _Value, unsigned char _Shift) {
_Shift &= 0x7;
return _Shift ? (_Value >> _Shift) | (_Value << (8 - _Shift)) : _Value;
}
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
_rotl16(unsigned short _Value, unsigned char _Shift) {
_Shift &= 0xf;
return _Shift ? (_Value << _Shift) | (_Value >> (16 - _Shift)) : _Value;
}
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
_rotr16(unsigned short _Value, unsigned char _Shift) {
_Shift &= 0xf;
return _Shift ? (_Value >> _Shift) | (_Value << (16 - _Shift)) : _Value;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_rotl(unsigned int _Value, int _Shift) {
_Shift &= 0x1f;
return _Shift ? (_Value << _Shift) | (_Value >> (32 - _Shift)) : _Value;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_rotr(unsigned int _Value, int _Shift) {
_Shift &= 0x1f;
return _Shift ? (_Value >> _Shift) | (_Value << (32 - _Shift)) : _Value;
}
-static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long __DEFAULT_FN_ATTRS
_lrotl(unsigned long _Value, int _Shift) {
_Shift &= 0x1f;
return _Shift ? (_Value << _Shift) | (_Value >> (32 - _Shift)) : _Value;
}
-static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long __DEFAULT_FN_ATTRS
_lrotr(unsigned long _Value, int _Shift) {
_Shift &= 0x1f;
return _Shift ? (_Value >> _Shift) | (_Value << (32 - _Shift)) : _Value;
}
static
-__inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+__inline__ unsigned __int64 __DEFAULT_FN_ATTRS
_rotl64(unsigned __int64 _Value, int _Shift) {
_Shift &= 0x3f;
return _Shift ? (_Value << _Shift) | (_Value >> (64 - _Shift)) : _Value;
}
static
-__inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+__inline__ unsigned __int64 __DEFAULT_FN_ATTRS
_rotr64(unsigned __int64 _Value, int _Shift) {
_Shift &= 0x3f;
return _Shift ? (_Value >> _Shift) | (_Value << (64 - _Shift)) : _Value;
@@ -498,71 +498,64 @@ _rotr64(unsigned __int64 _Value, int _Shift) {
/*----------------------------------------------------------------------------*\
|* Bit Counting and Testing
\*----------------------------------------------------------------------------*/
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_BitScanForward(unsigned long *_Index, unsigned long _Mask) {
if (!_Mask)
return 0;
*_Index = __builtin_ctzl(_Mask);
return 1;
}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_BitScanReverse(unsigned long *_Index, unsigned long _Mask) {
if (!_Mask)
return 0;
*_Index = 31 - __builtin_clzl(_Mask);
return 1;
}
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
-__popcnt16(unsigned short value) {
- return __builtin_popcount((int)value);
-}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
-__popcnt(unsigned int value) {
- return __builtin_popcount(value);
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittest(long const *a, long b) {
- return (*a >> b) & 1;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandcomplement(long *a, long b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a ^ (1 << b);
- return x;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandreset(long *a, long b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a & ~(1 << b);
- return x;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandset(long *a, long b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a | (1 << b);
- return x;
-}
-#if defined(__i386__) || defined(__x86_64__)
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_interlockedbittestandset(long volatile *__BitBase, long __BitPos) {
- unsigned char __Res;
- __asm__ ("xor %0, %0\n"
- "lock bts %2, %1\n"
- "setc %0\n"
- : "=r" (__Res), "+m"(*__BitBase)
- : "Ir"(__BitPos));
- return __Res;
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
+__popcnt16(unsigned short _Value) {
+ return __builtin_popcount((int)_Value);
+}
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+__popcnt(unsigned int _Value) {
+ return __builtin_popcount(_Value);
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittest(long const *_BitBase, long _BitPos) {
+ return (*_BitBase >> _BitPos) & 1;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandcomplement(long *_BitBase, long _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase ^ (1 << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandreset(long *_BitBase, long _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase & ~(1 << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandset(long *_BitBase, long _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase | (1 << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_interlockedbittestandset(long volatile *_BitBase, long _BitPos) {
+ long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_SEQ_CST);
+ return (_PrevVal >> _BitPos) & 1;
}
-#endif
#ifdef __x86_64__
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask) {
if (!_Mask)
return 0;
*_Index = __builtin_ctzll(_Mask);
return 1;
}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
_BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask) {
if (!_Mask)
return 0;
@@ -570,233 +563,232 @@ _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask) {
return 1;
}
static __inline__
-unsigned __int64 __attribute__((__always_inline__, __nodebug__))
- __popcnt64(unsigned __int64 value) {
- return __builtin_popcountll(value);
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittest64(__int64 const *a, __int64 b) {
- return (*a >> b) & 1;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandcomplement64(__int64 *a, __int64 b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a ^ (1ll << b);
- return x;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandreset64(__int64 *a, __int64 b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a & ~(1ll << b);
- return x;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_bittestandset64(__int64 *a, __int64 b) {
- unsigned char x = (*a >> b) & 1;
- *a = *a | (1ll << b);
- return x;
-}
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
-_interlockedbittestandset64(__int64 volatile *__BitBase, __int64 __BitPos) {
- unsigned char __Res;
- __asm__ ("xor %0, %0\n"
- "lock bts %2, %1\n"
- "setc %0\n"
- : "=r" (__Res), "+m"(*__BitBase)
- : "Ir"(__BitPos));
- return __Res;
+unsigned __int64 __DEFAULT_FN_ATTRS
+__popcnt64(unsigned __int64 _Value) {
+ return __builtin_popcountll(_Value);
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittest64(__int64 const *_BitBase, __int64 _BitPos) {
+ return (*_BitBase >> _BitPos) & 1;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandcomplement64(__int64 *_BitBase, __int64 _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase ^ (1ll << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandreset64(__int64 *_BitBase, __int64 _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase & ~(1ll << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_bittestandset64(__int64 *_BitBase, __int64 _BitPos) {
+ unsigned char _Res = (*_BitBase >> _BitPos) & 1;
+ *_BitBase = *_BitBase | (1ll << _BitPos);
+ return _Res;
+}
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_interlockedbittestandset64(__int64 volatile *_BitBase, __int64 _BitPos) {
+ long long _PrevVal =
+ __atomic_fetch_or(_BitBase, 1ll << _BitPos, __ATOMIC_SEQ_CST);
+ return (_PrevVal >> _BitPos) & 1;
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange Add
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedExchangeAdd8(char volatile *_Addend, char _Value) {
- return __atomic_add_fetch(_Addend, _Value, 0) - _Value;
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedExchangeAdd16(short volatile *_Addend, short _Value) {
- return __atomic_add_fetch(_Addend, _Value, 0) - _Value;
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value) {
- return __atomic_add_fetch(_Addend, _Value, 0) - _Value;
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange Sub
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedExchangeSub8(char volatile *_Subend, char _Value) {
- return __atomic_sub_fetch(_Subend, _Value, 0) + _Value;
+ return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedExchangeSub16(short volatile *_Subend, short _Value) {
- return __atomic_sub_fetch(_Subend, _Value, 0) + _Value;
+ return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
}
-static __inline__ long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long __DEFAULT_FN_ATTRS
_InterlockedExchangeSub(long volatile *_Subend, long _Value) {
- return __atomic_sub_fetch(_Subend, _Value, 0) + _Value;
+ return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value) {
- return __atomic_sub_fetch(_Subend, _Value, 0) + _Value;
+ return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Increment
\*----------------------------------------------------------------------------*/
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedIncrement16(short volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, 0);
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedIncrement64(__int64 volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, 0);
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Decrement
\*----------------------------------------------------------------------------*/
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedDecrement16(short volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, 0);
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedDecrement64(__int64 volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, 0);
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked And
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedAnd8(char volatile *_Value, char _Mask) {
- return __atomic_and_fetch(_Value, _Mask, 0);
+ return __atomic_and_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedAnd16(short volatile *_Value, short _Mask) {
- return __atomic_and_fetch(_Value, _Mask, 0);
+ return __atomic_and_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long __DEFAULT_FN_ATTRS
_InterlockedAnd(long volatile *_Value, long _Mask) {
- return __atomic_and_fetch(_Value, _Mask, 0);
+ return __atomic_and_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_and_fetch(_Value, _Mask, 0);
+ return __atomic_and_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Or
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedOr8(char volatile *_Value, char _Mask) {
- return __atomic_or_fetch(_Value, _Mask, 0);
+ return __atomic_or_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedOr16(short volatile *_Value, short _Mask) {
- return __atomic_or_fetch(_Value, _Mask, 0);
+ return __atomic_or_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long __DEFAULT_FN_ATTRS
_InterlockedOr(long volatile *_Value, long _Mask) {
- return __atomic_or_fetch(_Value, _Mask, 0);
+ return __atomic_or_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedOr64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_or_fetch(_Value, _Mask, 0);
+ return __atomic_or_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Xor
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedXor8(char volatile *_Value, char _Mask) {
- return __atomic_xor_fetch(_Value, _Mask, 0);
+ return __atomic_xor_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedXor16(short volatile *_Value, short _Mask) {
- return __atomic_xor_fetch(_Value, _Mask, 0);
+ return __atomic_xor_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
-static __inline__ long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long __DEFAULT_FN_ATTRS
_InterlockedXor(long volatile *_Value, long _Mask) {
- return __atomic_xor_fetch(_Value, _Mask, 0);
+ return __atomic_xor_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedXor64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_xor_fetch(_Value, _Mask, 0);
+ return __atomic_xor_fetch(_Value, _Mask, __ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedExchange8(char volatile *_Target, char _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, 0);
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
return _Value;
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedExchange16(short volatile *_Target, short _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, 0);
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
return _Value;
}
#ifdef __x86_64__
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedExchange64(__int64 volatile *_Target, __int64 _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, 0);
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
return _Value;
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Compare Exchange
\*----------------------------------------------------------------------------*/
-static __inline__ char __attribute__((__always_inline__, __nodebug__))
+static __inline__ char __DEFAULT_FN_ATTRS
_InterlockedCompareExchange8(char volatile *_Destination,
char _Exchange, char _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0);
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return _Comparand;
}
-static __inline__ short __attribute__((__always_inline__, __nodebug__))
+static __inline__ short __DEFAULT_FN_ATTRS
_InterlockedCompareExchange16(short volatile *_Destination,
short _Exchange, short _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0);
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return _Comparand;
}
-static __inline__ __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __int64 __DEFAULT_FN_ATTRS
_InterlockedCompareExchange64(__int64 volatile *_Destination,
__int64 _Exchange, __int64 _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0);
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return _Comparand;
}
/*----------------------------------------------------------------------------*\
|* Barriers
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__attribute__((deprecated("use other intrinsics or C++11 atomics instead")))
+static __inline__ void __DEFAULT_FN_ATTRS
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_ReadWriteBarrier(void) {
__asm__ volatile ("" : : : "memory");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__attribute__((deprecated("use other intrinsics or C++11 atomics instead")))
+static __inline__ void __DEFAULT_FN_ATTRS
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_ReadBarrier(void) {
__asm__ volatile ("" : : : "memory");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__attribute__((deprecated("use other intrinsics or C++11 atomics instead")))
+static __inline__ void __DEFAULT_FN_ATTRS
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_WriteBarrier(void) {
__asm__ volatile ("" : : : "memory");
}
#endif
#ifdef __x86_64__
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__faststorefence(void) {
__asm__ volatile("lock orq $0, (%%rsp)" : : : "memory");
}
@@ -811,33 +803,33 @@ __faststorefence(void) {
(__offset))
#ifdef __i386__
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
__readfsbyte(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned char, __offset);
}
-static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readfsqword(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned __int64, __offset);
}
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
__readfsword(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned short, __offset);
}
#endif
#ifdef __x86_64__
-static __inline__ unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
__readgsbyte(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned char, __offset);
}
-static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long __DEFAULT_FN_ATTRS
__readgsdword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned long, __offset);
}
-static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readgsqword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned __int64, __offset);
}
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
__readgsword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned short, __offset);
}
@@ -847,44 +839,44 @@ __readgsword(unsigned long __offset) {
|* movs, stos
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__movsb(unsigned char *__dst, unsigned char const *__src, size_t __n) {
__asm__("rep movsb" : : "D"(__dst), "S"(__src), "c"(__n)
: "%edi", "%esi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) {
__asm__("rep movsl" : : "D"(__dst), "S"(__src), "c"(__n)
: "%edi", "%esi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) {
__asm__("rep movsh" : : "D"(__dst), "S"(__src), "c"(__n)
: "%edi", "%esi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__stosb(unsigned char *__dst, unsigned char __x, size_t __n) {
__asm__("rep stosb" : : "D"(__dst), "a"(__x), "c"(__n)
: "%edi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__stosd(unsigned long *__dst, unsigned long __x, size_t __n) {
__asm__("rep stosl" : : "D"(__dst), "a"(__x), "c"(__n)
: "%edi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__stosw(unsigned short *__dst, unsigned short __x, size_t __n) {
__asm__("rep stosh" : : "D"(__dst), "a"(__x), "c"(__n)
: "%edi", "%ecx");
}
#endif
#ifdef __x86_64__
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__movsq(unsigned long long *__dst, unsigned long long const *__src, size_t __n) {
__asm__("rep movsq" : : "D"(__dst), "S"(__src), "c"(__n)
: "%edi", "%esi", "%ecx");
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
__asm__("rep stosq" : : "D"(__dst), "a"(__x), "c"(__n)
: "%edi", "%ecx");
@@ -894,32 +886,32 @@ __stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
/*----------------------------------------------------------------------------*\
|* Misc
\*----------------------------------------------------------------------------*/
-static __inline__ void * __attribute__((__always_inline__, __nodebug__))
+static __inline__ void * __DEFAULT_FN_ATTRS
_AddressOfReturnAddress(void) {
return (void*)((char*)__builtin_frame_address(0) + sizeof(void*));
}
-static __inline__ void * __attribute__((__always_inline__, __nodebug__))
+static __inline__ void * __DEFAULT_FN_ATTRS
_ReturnAddress(void) {
return __builtin_return_address(0);
}
#if defined(__i386__) || defined(__x86_64__)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__cpuid(int __info[4], int __level) {
__asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
: "a"(__level));
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__cpuidex(int __info[4], int __level, int __ecx) {
__asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
: "a"(__level), "c"(__ecx));
}
-static __inline__ unsigned __int64 __cdecl __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __cdecl __DEFAULT_FN_ATTRS
_xgetbv(unsigned int __xcr_no) {
unsigned int __eax, __edx;
__asm__ ("xgetbv" : "=a" (__eax), "=d" (__edx) : "c" (__xcr_no));
return ((unsigned __int64)__edx << 32) | __eax;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__halt(void) {
__asm__ volatile ("hlt");
}
@@ -929,7 +921,7 @@ __halt(void) {
|* Privileged intrinsics
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
-static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readmsr(unsigned long __register) {
// Loads the contents of a 64-bit model specific register (MSR) specified in
// the ECX register into registers EDX:EAX. The EDX register is loaded with
@@ -943,14 +935,14 @@ __readmsr(unsigned long __register) {
return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax;
}
-static __inline__ unsigned long __attribute__((always_inline, __nodebug__))
+static __inline__ unsigned long __DEFAULT_FN_ATTRS
__readcr3(void) {
unsigned long __cr3_val;
__asm__ __volatile__ ("mov %%cr3, %0" : "=q"(__cr3_val) : : "memory");
return __cr3_val;
}
-static __inline__ void __attribute__((always_inline, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
__writecr3(unsigned int __cr3_val) {
__asm__ ("mov %0, %%cr3" : : "q"(__cr3_val) : "memory");
}
@@ -960,5 +952,7 @@ __writecr3(unsigned int __cr3_val) {
}
#endif
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __INTRIN_H */
#endif /* _MSC_VER */
diff --git a/contrib/llvm/tools/clang/lib/Headers/__stddef_max_align_t.h b/contrib/llvm/tools/clang/lib/Headers/__stddef_max_align_t.h
index a06f412..1e10ca9 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__stddef_max_align_t.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__stddef_max_align_t.h
@@ -26,15 +26,18 @@
#ifndef __CLANG_MAX_ALIGN_T_DEFINED
#define __CLANG_MAX_ALIGN_T_DEFINED
-#ifndef _MSC_VER
+#if defined(_MSC_VER)
+typedef double max_align_t;
+#elif defined(__APPLE__)
+typedef long double max_align_t;
+#else
+// Define 'max_align_t' to match the GCC definition.
typedef struct {
long long __clang_max_align_nonce1
__attribute__((__aligned__(__alignof__(long long))));
long double __clang_max_align_nonce2
__attribute__((__aligned__(__alignof__(long double))));
} max_align_t;
-#else
-typedef double max_align_t;
#endif
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
index 2bfa027..9f594ee 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
@@ -29,31 +29,34 @@
# error "AES instructions not enabled"
#else
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesenc_si128(__m128i __V, __m128i __R)
{
return (__m128i)__builtin_ia32_aesenc128(__V, __R);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesenclast_si128(__m128i __V, __m128i __R)
{
return (__m128i)__builtin_ia32_aesenclast128(__V, __R);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesdec_si128(__m128i __V, __m128i __R)
{
return (__m128i)__builtin_ia32_aesdec128(__V, __R);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesdeclast_si128(__m128i __V, __m128i __R)
{
return (__m128i)__builtin_ia32_aesdeclast128(__V, __R);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesimc_si128(__m128i __V)
{
return (__m128i)__builtin_ia32_aesimc128(__V);
@@ -62,6 +65,8 @@ _mm_aesimc_si128(__m128i __V)
#define _mm_aeskeygenassist_si128(C, R) \
__builtin_ia32_aeskeygenassist128((C), (R))
+#undef __DEFAULT_FN_ATTRS
+
#endif
#endif /* _WMMINTRIN_AES_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/adxintrin.h b/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
index 9db8bcb..b8eb9cb 100644
--- a/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
@@ -28,9 +28,12 @@
#ifndef __ADXINTRIN_H
#define __ADXINTRIN_H
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* Intrinsics that are available only if __ADX__ defined */
#ifdef __ADX__
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
unsigned int *__p)
{
@@ -38,7 +41,7 @@ _addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
}
#ifdef __x86_64__
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarryx_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y, unsigned long long *__p)
{
@@ -48,7 +51,7 @@ _addcarryx_u64(unsigned char __cf, unsigned long long __x,
#endif
/* Intrinsics that are also available if __ADX__ undefined */
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarry_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
unsigned int *__p)
{
@@ -56,7 +59,7 @@ _addcarry_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
}
#ifdef __x86_64__
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarry_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y, unsigned long long *__p)
{
@@ -64,7 +67,7 @@ _addcarry_u64(unsigned char __cf, unsigned long long __x,
}
#endif
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_subborrow_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
unsigned int *__p)
{
@@ -72,7 +75,7 @@ _subborrow_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
}
#ifdef __x86_64__
-static __inline unsigned char __attribute__((__always_inline__, __nodebug__))
+static __inline unsigned char __DEFAULT_FN_ATTRS
_subborrow_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y, unsigned long long *__p)
{
@@ -80,4 +83,6 @@ _subborrow_u64(unsigned char __cf, unsigned long long __x,
}
#endif
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __ADXINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/altivec.h b/contrib/llvm/tools/clang/lib/Headers/altivec.h
index 0ac0841..f52bcbc 100644
--- a/contrib/llvm/tools/clang/lib/Headers/altivec.h
+++ b/contrib/llvm/tools/clang/lib/Headers/altivec.h
@@ -29,265 +29,286 @@
/* constants for mapping CR6 bits to predicate result. */
-#define __CR6_EQ 0
+#define __CR6_EQ 0
#define __CR6_EQ_REV 1
-#define __CR6_LT 2
+#define __CR6_LT 2
#define __CR6_LT_REV 3
#define __ATTRS_o_ai __attribute__((__overloadable__, __always_inline__))
-static vector signed char __ATTRS_o_ai
-vec_perm(vector signed char __a, vector signed char __b, vector unsigned char __c);
+static vector signed char __ATTRS_o_ai vec_perm(vector signed char __a,
+ vector signed char __b,
+ vector unsigned char __c);
-static vector unsigned char __ATTRS_o_ai
-vec_perm(vector unsigned char __a,
- vector unsigned char __b,
- vector unsigned char __c);
+static vector unsigned char __ATTRS_o_ai vec_perm(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned char __c);
-static vector bool char __ATTRS_o_ai
-vec_perm(vector bool char __a, vector bool char __b, vector unsigned char __c);
+static vector bool char __ATTRS_o_ai vec_perm(vector bool char __a,
+ vector bool char __b,
+ vector unsigned char __c);
-static vector short __ATTRS_o_ai
-vec_perm(vector short __a, vector short __b, vector unsigned char __c);
+static vector short __ATTRS_o_ai vec_perm(vector signed short __a,
+ vector signed short __b,
+ vector unsigned char __c);
-static vector unsigned short __ATTRS_o_ai
-vec_perm(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned char __c);
+static vector unsigned short __ATTRS_o_ai vec_perm(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned char __c);
-static vector bool short __ATTRS_o_ai
-vec_perm(vector bool short __a, vector bool short __b, vector unsigned char __c);
+static vector bool short __ATTRS_o_ai vec_perm(vector bool short __a,
+ vector bool short __b,
+ vector unsigned char __c);
-static vector pixel __ATTRS_o_ai
-vec_perm(vector pixel __a, vector pixel __b, vector unsigned char __c);
+static vector pixel __ATTRS_o_ai vec_perm(vector pixel __a, vector pixel __b,
+ vector unsigned char __c);
-static vector int __ATTRS_o_ai
-vec_perm(vector int __a, vector int __b, vector unsigned char __c);
+static vector int __ATTRS_o_ai vec_perm(vector signed int __a,
+ vector signed int __b,
+ vector unsigned char __c);
-static vector unsigned int __ATTRS_o_ai
-vec_perm(vector unsigned int __a, vector unsigned int __b, vector unsigned char __c);
+static vector unsigned int __ATTRS_o_ai vec_perm(vector unsigned int __a,
+ vector unsigned int __b,
+ vector unsigned char __c);
-static vector bool int __ATTRS_o_ai
-vec_perm(vector bool int __a, vector bool int __b, vector unsigned char __c);
+static vector bool int __ATTRS_o_ai vec_perm(vector bool int __a,
+ vector bool int __b,
+ vector unsigned char __c);
-static vector float __ATTRS_o_ai
-vec_perm(vector float __a, vector float __b, vector unsigned char __c);
+static vector float __ATTRS_o_ai vec_perm(vector float __a, vector float __b,
+ vector unsigned char __c);
-static vector unsigned char __ATTRS_o_ai
-vec_xor(vector unsigned char __a, vector unsigned char __b);
+#ifdef __VSX__
+static vector long long __ATTRS_o_ai vec_perm(vector signed long long __a,
+ vector signed long long __b,
+ vector unsigned char __c);
+
+static vector unsigned long long __ATTRS_o_ai
+vec_perm(vector unsigned long long __a, vector unsigned long long __b,
+ vector unsigned char __c);
+
+static vector bool long long __ATTRS_o_ai
+vec_perm(vector bool long long __a, vector bool long long __b,
+ vector unsigned char __c);
+
+static vector double __ATTRS_o_ai vec_perm(vector double __a, vector double __b,
+ vector unsigned char __c);
+#endif
+
+static vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a,
+ vector unsigned char __b);
/* vec_abs */
#define __builtin_altivec_abs_v16qi vec_abs
-#define __builtin_altivec_abs_v8hi vec_abs
-#define __builtin_altivec_abs_v4si vec_abs
+#define __builtin_altivec_abs_v8hi vec_abs
+#define __builtin_altivec_abs_v4si vec_abs
-static vector signed char __ATTRS_o_ai
-vec_abs(vector signed char __a)
-{
+static vector signed char __ATTRS_o_ai vec_abs(vector signed char __a) {
return __builtin_altivec_vmaxsb(__a, -__a);
}
-static vector signed short __ATTRS_o_ai
-vec_abs(vector signed short __a)
-{
+static vector signed short __ATTRS_o_ai vec_abs(vector signed short __a) {
return __builtin_altivec_vmaxsh(__a, -__a);
}
-static vector signed int __ATTRS_o_ai
-vec_abs(vector signed int __a)
-{
+static vector signed int __ATTRS_o_ai vec_abs(vector signed int __a) {
return __builtin_altivec_vmaxsw(__a, -__a);
}
-static vector float __ATTRS_o_ai
-vec_abs(vector float __a)
-{
- vector unsigned int __res = (vector unsigned int)__a
- & (vector unsigned int)(0x7FFFFFFF);
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed long long __ATTRS_o_ai
+vec_abs(vector signed long long __a) {
+ return __builtin_altivec_vmaxsd(__a, -__a);
+}
+#endif
+
+static vector float __ATTRS_o_ai vec_abs(vector float __a) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)(0x7FFFFFFF);
return (vector float)__res;
}
-/* vec_abss */
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector double __ATTRS_o_ai vec_abs(vector double __a) {
+ vector unsigned long long __res = { 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF };
+ __res &= (vector unsigned int)__a;
+ return (vector double)__res;
+}
+#endif
+/* vec_abss */
#define __builtin_altivec_abss_v16qi vec_abss
-#define __builtin_altivec_abss_v8hi vec_abss
-#define __builtin_altivec_abss_v4si vec_abss
+#define __builtin_altivec_abss_v8hi vec_abss
+#define __builtin_altivec_abss_v4si vec_abss
-static vector signed char __ATTRS_o_ai
-vec_abss(vector signed char __a)
-{
- return __builtin_altivec_vmaxsb
- (__a, __builtin_altivec_vsubsbs((vector signed char)(0), __a));
+static vector signed char __ATTRS_o_ai vec_abss(vector signed char __a) {
+ return __builtin_altivec_vmaxsb(
+ __a, __builtin_altivec_vsubsbs((vector signed char)(0), __a));
}
-static vector signed short __ATTRS_o_ai
-vec_abss(vector signed short __a)
-{
- return __builtin_altivec_vmaxsh
- (__a, __builtin_altivec_vsubshs((vector signed short)(0), __a));
+static vector signed short __ATTRS_o_ai vec_abss(vector signed short __a) {
+ return __builtin_altivec_vmaxsh(
+ __a, __builtin_altivec_vsubshs((vector signed short)(0), __a));
}
-static vector signed int __ATTRS_o_ai
-vec_abss(vector signed int __a)
-{
- return __builtin_altivec_vmaxsw
- (__a, __builtin_altivec_vsubsws((vector signed int)(0), __a));
+static vector signed int __ATTRS_o_ai vec_abss(vector signed int __a) {
+ return __builtin_altivec_vmaxsw(
+ __a, __builtin_altivec_vsubsws((vector signed int)(0), __a));
}
/* vec_add */
-static vector signed char __ATTRS_o_ai
-vec_add(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_add(vector signed char __a,
+ vector signed char __b) {
return __a + __b;
}
-static vector signed char __ATTRS_o_ai
-vec_add(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_add(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a + __b;
}
-static vector signed char __ATTRS_o_ai
-vec_add(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_add(vector signed char __a,
+ vector bool char __b) {
return __a + (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_add(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_add(vector unsigned char __a,
+ vector unsigned char __b) {
return __a + __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_add(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_add(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a + __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_add(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_add(vector unsigned char __a,
+ vector bool char __b) {
return __a + (vector unsigned char)__b;
}
-static vector short __ATTRS_o_ai
-vec_add(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_add(vector short __a, vector short __b) {
return __a + __b;
}
-static vector short __ATTRS_o_ai
-vec_add(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_add(vector bool short __a,
+ vector short __b) {
return (vector short)__a + __b;
}
-static vector short __ATTRS_o_ai
-vec_add(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_add(vector short __a,
+ vector bool short __b) {
return __a + (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_add(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_add(vector unsigned short __a,
+ vector unsigned short __b) {
return __a + __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_add(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_add(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a + __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_add(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_add(vector unsigned short __a,
+ vector bool short __b) {
return __a + (vector unsigned short)__b;
}
-static vector int __ATTRS_o_ai
-vec_add(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_add(vector int __a, vector int __b) {
return __a + __b;
}
-static vector int __ATTRS_o_ai
-vec_add(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_add(vector bool int __a, vector int __b) {
return (vector int)__a + __b;
}
-static vector int __ATTRS_o_ai
-vec_add(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_add(vector int __a, vector bool int __b) {
return __a + (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_add(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_add(vector unsigned int __a,
+ vector unsigned int __b) {
return __a + __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_add(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_add(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a + __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_add(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_add(vector unsigned int __a,
+ vector bool int __b) {
return __a + (vector unsigned int)__b;
}
-static vector float __ATTRS_o_ai
-vec_add(vector float __a, vector float __b)
-{
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed long long __ATTRS_o_ai
+vec_add(vector signed long long __a, vector signed long long __b) {
+ return __a + __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_add(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a + __b;
+}
+
+static vector signed __int128 __ATTRS_o_ai vec_add(vector signed __int128 __a,
+ vector signed __int128 __b) {
+ return __a + __b;
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_add(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __a + __b;
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
+static vector float __ATTRS_o_ai vec_add(vector float __a, vector float __b) {
return __a + __b;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_add(vector double __a, vector double __b) {
+ return __a + __b;
+}
+#endif // __VSX__
+
/* vec_vaddubm */
#define __builtin_altivec_vaddubm vec_vaddubm
-static vector signed char __ATTRS_o_ai
-vec_vaddubm(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddubm(vector signed char __a,
+ vector signed char __b) {
return __a + __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vaddubm(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddubm(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a + __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vaddubm(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddubm(vector signed char __a,
+ vector bool char __b) {
return __a + (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubm(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubm(vector unsigned char __a,
+ vector unsigned char __b) {
return __a + __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubm(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubm(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a + __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubm(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubm(vector unsigned char __a,
+ vector bool char __b) {
return __a + (vector unsigned char)__b;
}
@@ -295,39 +316,33 @@ vec_vaddubm(vector unsigned char __a, vector bool char __b)
#define __builtin_altivec_vadduhm vec_vadduhm
-static vector short __ATTRS_o_ai
-vec_vadduhm(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vadduhm(vector short __a,
+ vector short __b) {
return __a + __b;
}
-static vector short __ATTRS_o_ai
-vec_vadduhm(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vadduhm(vector bool short __a,
+ vector short __b) {
return (vector short)__a + __b;
}
-static vector short __ATTRS_o_ai
-vec_vadduhm(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vadduhm(vector short __a,
+ vector bool short __b) {
return __a + (vector short)__b;
}
static vector unsigned short __ATTRS_o_ai
-vec_vadduhm(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vadduhm(vector unsigned short __a, vector unsigned short __b) {
return __a + __b;
}
static vector unsigned short __ATTRS_o_ai
-vec_vadduhm(vector bool short __a, vector unsigned short __b)
-{
+vec_vadduhm(vector bool short __a, vector unsigned short __b) {
return (vector unsigned short)__a + __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vadduhm(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vadduhm(vector unsigned short __a,
+ vector bool short __b) {
return __a + (vector unsigned short)__b;
}
@@ -335,1934 +350,2231 @@ vec_vadduhm(vector unsigned short __a, vector bool short __b)
#define __builtin_altivec_vadduwm vec_vadduwm
-static vector int __ATTRS_o_ai
-vec_vadduwm(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vadduwm(vector int __a, vector int __b) {
return __a + __b;
}
-static vector int __ATTRS_o_ai
-vec_vadduwm(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vadduwm(vector bool int __a,
+ vector int __b) {
return (vector int)__a + __b;
}
-static vector int __ATTRS_o_ai
-vec_vadduwm(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vadduwm(vector int __a,
+ vector bool int __b) {
return __a + (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vadduwm(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduwm(vector unsigned int __a,
+ vector unsigned int __b) {
return __a + __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vadduwm(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduwm(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a + __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vadduwm(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduwm(vector unsigned int __a,
+ vector bool int __b) {
return __a + (vector unsigned int)__b;
}
/* vec_vaddfp */
-#define __builtin_altivec_vaddfp vec_vaddfp
+#define __builtin_altivec_vaddfp vec_vaddfp
static vector float __attribute__((__always_inline__))
-vec_vaddfp(vector float __a, vector float __b)
-{
+vec_vaddfp(vector float __a, vector float __b) {
return __a + __b;
}
/* vec_addc */
-static vector unsigned int __attribute__((__always_inline__))
-vec_addc(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_addc(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vaddcuw(__a, __b);
}
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed __int128 __ATTRS_o_ai
+vec_addc(vector signed __int128 __a, vector signed __int128 __b) {
+ return __builtin_altivec_vaddcuq(__a, __b);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_addc(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __builtin_altivec_vaddcuq(__a, __b);
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
/* vec_vaddcuw */
static vector unsigned int __attribute__((__always_inline__))
-vec_vaddcuw(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vaddcuw(vector unsigned int __a, vector unsigned int __b) {
return __builtin_altivec_vaddcuw(__a, __b);
}
/* vec_adds */
-static vector signed char __ATTRS_o_ai
-vec_adds(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_adds(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vaddsbs(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_adds(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_adds(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vaddsbs((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_adds(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_adds(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vaddsbs(__a, (vector signed char)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_adds(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_adds(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vaddubs(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_adds(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_adds(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vaddubs((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_adds(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_adds(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vaddubs(__a, (vector unsigned char)__b);
}
-static vector short __ATTRS_o_ai
-vec_adds(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_adds(vector short __a, vector short __b) {
return __builtin_altivec_vaddshs(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_adds(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_adds(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vaddshs((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_adds(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_adds(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vaddshs(__a, (vector short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_adds(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_adds(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vadduhs(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_adds(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_adds(vector bool short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vadduhs((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_adds(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_adds(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vadduhs(__a, (vector unsigned short)__b);
}
-static vector int __ATTRS_o_ai
-vec_adds(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_adds(vector int __a, vector int __b) {
return __builtin_altivec_vaddsws(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_adds(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_adds(vector bool int __a, vector int __b) {
return __builtin_altivec_vaddsws((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_adds(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_adds(vector int __a, vector bool int __b) {
return __builtin_altivec_vaddsws(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_adds(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_adds(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vadduws(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_adds(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_adds(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vadduws((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_adds(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_adds(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vadduws(__a, (vector unsigned int)__b);
}
/* vec_vaddsbs */
-static vector signed char __ATTRS_o_ai
-vec_vaddsbs(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddsbs(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vaddsbs(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vaddsbs(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddsbs(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vaddsbs((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vaddsbs(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vaddsbs(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vaddsbs(__a, (vector signed char)__b);
}
/* vec_vaddubs */
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubs(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubs(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vaddubs(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubs(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubs(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vaddubs((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vaddubs(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vaddubs(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vaddubs(__a, (vector unsigned char)__b);
}
/* vec_vaddshs */
-static vector short __ATTRS_o_ai
-vec_vaddshs(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vaddshs(vector short __a,
+ vector short __b) {
return __builtin_altivec_vaddshs(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vaddshs(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vaddshs(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vaddshs((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vaddshs(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vaddshs(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vaddshs(__a, (vector short)__b);
}
/* vec_vadduhs */
static vector unsigned short __ATTRS_o_ai
-vec_vadduhs(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vadduhs(vector unsigned short __a, vector unsigned short __b) {
return __builtin_altivec_vadduhs(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_vadduhs(vector bool short __a, vector unsigned short __b)
-{
+vec_vadduhs(vector bool short __a, vector unsigned short __b) {
return __builtin_altivec_vadduhs((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vadduhs(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vadduhs(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vadduhs(__a, (vector unsigned short)__b);
}
/* vec_vaddsws */
-static vector int __ATTRS_o_ai
-vec_vaddsws(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vaddsws(vector int __a, vector int __b) {
return __builtin_altivec_vaddsws(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vaddsws(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vaddsws(vector bool int __a,
+ vector int __b) {
return __builtin_altivec_vaddsws((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vaddsws(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vaddsws(vector int __a,
+ vector bool int __b) {
return __builtin_altivec_vaddsws(__a, (vector int)__b);
}
/* vec_vadduws */
-static vector unsigned int __ATTRS_o_ai
-vec_vadduws(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduws(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vadduws(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vadduws(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduws(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vadduws((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vadduws(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vadduws(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vadduws(__a, (vector unsigned int)__b);
}
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+/* vec_vadduqm */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vadduqm(vector signed __int128 __a, vector signed __int128 __b) {
+ return __a + __b;
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vadduqm(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __a + __b;
+}
+
+/* vec_vaddeuqm */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vaddeuqm(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vaddeuqm(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vaddeuqm(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vaddeuqm(__a, __b, __c);
+}
+
+/* vec_vaddcuq */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vaddcuq(vector signed __int128 __a, vector signed __int128 __b) {
+ return __builtin_altivec_vaddcuq(__a, __b);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vaddcuq(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __builtin_altivec_vaddcuq(__a, __b);
+}
+
+/* vec_vaddecuq */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vaddecuq(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vaddecuq(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vaddecuq(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vaddecuq(__a, __b, __c);
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
/* vec_and */
#define __builtin_altivec_vand vec_and
-static vector signed char __ATTRS_o_ai
-vec_and(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_and(vector signed char __a,
+ vector signed char __b) {
return __a & __b;
}
-static vector signed char __ATTRS_o_ai
-vec_and(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_and(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a & __b;
}
-static vector signed char __ATTRS_o_ai
-vec_and(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_and(vector signed char __a,
+ vector bool char __b) {
return __a & (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_and(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_and(vector unsigned char __a,
+ vector unsigned char __b) {
return __a & __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_and(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_and(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a & __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_and(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_and(vector unsigned char __a,
+ vector bool char __b) {
return __a & (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_and(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_and(vector bool char __a,
+ vector bool char __b) {
return __a & __b;
}
-static vector short __ATTRS_o_ai
-vec_and(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_and(vector short __a, vector short __b) {
return __a & __b;
}
-static vector short __ATTRS_o_ai
-vec_and(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_and(vector bool short __a,
+ vector short __b) {
return (vector short)__a & __b;
}
-static vector short __ATTRS_o_ai
-vec_and(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_and(vector short __a,
+ vector bool short __b) {
return __a & (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_and(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_and(vector unsigned short __a,
+ vector unsigned short __b) {
return __a & __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_and(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_and(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a & __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_and(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_and(vector unsigned short __a,
+ vector bool short __b) {
return __a & (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_and(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_and(vector bool short __a,
+ vector bool short __b) {
return __a & __b;
}
-static vector int __ATTRS_o_ai
-vec_and(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_and(vector int __a, vector int __b) {
return __a & __b;
}
-static vector int __ATTRS_o_ai
-vec_and(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_and(vector bool int __a, vector int __b) {
return (vector int)__a & __b;
}
-static vector int __ATTRS_o_ai
-vec_and(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_and(vector int __a, vector bool int __b) {
return __a & (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_and(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_and(vector unsigned int __a,
+ vector unsigned int __b) {
return __a & __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_and(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_and(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a & __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_and(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_and(vector unsigned int __a,
+ vector bool int __b) {
return __a & (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_and(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_and(vector bool int __a,
+ vector bool int __b) {
return __a & __b;
}
-static vector float __ATTRS_o_ai
-vec_and(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_and(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_and(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_and(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_and(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_and(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_and(vector bool long long __a, vector double __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & (vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector double __ATTRS_o_ai vec_and(vector double __a, vector bool long long __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & (vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector double __ATTRS_o_ai vec_and(vector double __a, vector double __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & (vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_and(vector signed long long __a, vector signed long long __b) {
+ return __a & __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_and(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a & __b;
+}
+
+static vector signed long long __ATTRS_o_ai vec_and(vector signed long long __a,
+ vector bool long long __b) {
+ return __a & (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_and(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a & __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_and(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a & __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_and(vector unsigned long long __a, vector bool long long __b) {
+ return __a & (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_and(vector bool long long __a,
+ vector bool long long __b) {
+ return __a & __b;
+}
+#endif
+
/* vec_vand */
-static vector signed char __ATTRS_o_ai
-vec_vand(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vand(vector signed char __a,
+ vector signed char __b) {
return __a & __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vand(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vand(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a & __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vand(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vand(vector signed char __a,
+ vector bool char __b) {
return __a & (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vand(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vand(vector unsigned char __a,
+ vector unsigned char __b) {
return __a & __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vand(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vand(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a & __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vand(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vand(vector unsigned char __a,
+ vector bool char __b) {
return __a & (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_vand(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vand(vector bool char __a,
+ vector bool char __b) {
return __a & __b;
}
-static vector short __ATTRS_o_ai
-vec_vand(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vand(vector short __a, vector short __b) {
return __a & __b;
}
-static vector short __ATTRS_o_ai
-vec_vand(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vand(vector bool short __a,
+ vector short __b) {
return (vector short)__a & __b;
}
-static vector short __ATTRS_o_ai
-vec_vand(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vand(vector short __a,
+ vector bool short __b) {
return __a & (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vand(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vand(vector unsigned short __a,
+ vector unsigned short __b) {
return __a & __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vand(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vand(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a & __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vand(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vand(vector unsigned short __a,
+ vector bool short __b) {
return __a & (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_vand(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_vand(vector bool short __a,
+ vector bool short __b) {
return __a & __b;
}
-static vector int __ATTRS_o_ai
-vec_vand(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vand(vector int __a, vector int __b) {
return __a & __b;
}
-static vector int __ATTRS_o_ai
-vec_vand(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vand(vector bool int __a, vector int __b) {
return (vector int)__a & __b;
}
-static vector int __ATTRS_o_ai
-vec_vand(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vand(vector int __a, vector bool int __b) {
return __a & (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vand(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vand(vector unsigned int __a,
+ vector unsigned int __b) {
return __a & __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vand(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vand(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a & __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vand(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vand(vector unsigned int __a,
+ vector bool int __b) {
return __a & (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_vand(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_vand(vector bool int __a,
+ vector bool int __b) {
return __a & __b;
}
-static vector float __ATTRS_o_ai
-vec_vand(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vand(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vand(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vand(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vand(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vand(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_vand(vector signed long long __a, vector signed long long __b) {
+ return __a & __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vand(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a & __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vand(vector signed long long __a, vector bool long long __b) {
+ return __a & (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vand(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a & __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vand(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a & __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vand(vector unsigned long long __a, vector bool long long __b) {
+ return __a & (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_vand(vector bool long long __a,
+ vector bool long long __b) {
+ return __a & __b;
+}
+#endif
+
/* vec_andc */
#define __builtin_altivec_vandc vec_andc
-static vector signed char __ATTRS_o_ai
-vec_andc(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_andc(vector signed char __a,
+ vector signed char __b) {
return __a & ~__b;
}
-static vector signed char __ATTRS_o_ai
-vec_andc(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_andc(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a & ~__b;
}
-static vector signed char __ATTRS_o_ai
-vec_andc(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_andc(vector signed char __a,
+ vector bool char __b) {
return __a & ~(vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_andc(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_andc(vector unsigned char __a,
+ vector unsigned char __b) {
return __a & ~__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_andc(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_andc(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a & ~__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_andc(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_andc(vector unsigned char __a,
+ vector bool char __b) {
return __a & ~(vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_andc(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_andc(vector bool char __a,
+ vector bool char __b) {
return __a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_andc(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_andc(vector short __a, vector short __b) {
return __a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_andc(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_andc(vector bool short __a,
+ vector short __b) {
return (vector short)__a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_andc(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_andc(vector short __a,
+ vector bool short __b) {
return __a & ~(vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_andc(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_andc(vector unsigned short __a,
+ vector unsigned short __b) {
return __a & ~__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_andc(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_andc(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a & ~__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_andc(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_andc(vector unsigned short __a,
+ vector bool short __b) {
return __a & ~(vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_andc(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_andc(vector bool short __a,
+ vector bool short __b) {
return __a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_andc(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_andc(vector int __a, vector int __b) {
return __a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_andc(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_andc(vector bool int __a, vector int __b) {
return (vector int)__a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_andc(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_andc(vector int __a, vector bool int __b) {
return __a & ~(vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_andc(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_andc(vector unsigned int __a,
+ vector unsigned int __b) {
return __a & ~__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_andc(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_andc(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a & ~__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_andc(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_andc(vector unsigned int __a,
+ vector bool int __b) {
return __a & ~(vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_andc(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_andc(vector bool int __a,
+ vector bool int __b) {
return __a & ~__b;
}
-static vector float __ATTRS_o_ai
-vec_andc(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_andc(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_andc(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_andc(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_andc(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_andc(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_andc(vector bool long long __a, vector double __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & ~(vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector double __ATTRS_o_ai
+vec_andc(vector double __a, vector bool long long __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & ~(vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector double __ATTRS_o_ai vec_andc(vector double __a, vector double __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a & ~(vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_andc(vector signed long long __a, vector signed long long __b) {
+ return __a & ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_andc(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a & ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_andc(vector signed long long __a, vector bool long long __b) {
+ return __a & ~(vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_andc(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a & ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_andc(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a & ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_andc(vector unsigned long long __a, vector bool long long __b) {
+ return __a & ~(vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_andc(vector bool long long __a,
+ vector bool long long __b) {
+ return __a & ~__b;
+}
+#endif
+
/* vec_vandc */
-static vector signed char __ATTRS_o_ai
-vec_vandc(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vandc(vector signed char __a,
+ vector signed char __b) {
return __a & ~__b;
}
-static vector signed char __ATTRS_o_ai
-vec_vandc(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vandc(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a & ~__b;
}
-static vector signed char __ATTRS_o_ai
-vec_vandc(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vandc(vector signed char __a,
+ vector bool char __b) {
return __a & ~(vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vandc(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vandc(vector unsigned char __a,
+ vector unsigned char __b) {
return __a & ~__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vandc(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vandc(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a & ~__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vandc(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vandc(vector unsigned char __a,
+ vector bool char __b) {
return __a & ~(vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_vandc(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vandc(vector bool char __a,
+ vector bool char __b) {
return __a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_vandc(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vandc(vector short __a, vector short __b) {
return __a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_vandc(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vandc(vector bool short __a,
+ vector short __b) {
return (vector short)__a & ~__b;
}
-static vector short __ATTRS_o_ai
-vec_vandc(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vandc(vector short __a,
+ vector bool short __b) {
return __a & ~(vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vandc(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vandc(vector unsigned short __a,
+ vector unsigned short __b) {
return __a & ~__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vandc(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vandc(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a & ~__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vandc(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vandc(vector unsigned short __a,
+ vector bool short __b) {
return __a & ~(vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_vandc(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_vandc(vector bool short __a,
+ vector bool short __b) {
return __a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_vandc(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vandc(vector int __a, vector int __b) {
return __a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_vandc(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vandc(vector bool int __a, vector int __b) {
return (vector int)__a & ~__b;
}
-static vector int __ATTRS_o_ai
-vec_vandc(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vandc(vector int __a, vector bool int __b) {
return __a & ~(vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vandc(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vandc(vector unsigned int __a,
+ vector unsigned int __b) {
return __a & ~__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vandc(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vandc(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a & ~__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vandc(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vandc(vector unsigned int __a,
+ vector bool int __b) {
return __a & ~(vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_vandc(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_vandc(vector bool int __a,
+ vector bool int __b) {
return __a & ~__b;
}
-static vector float __ATTRS_o_ai
-vec_vandc(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vandc(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vandc(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vandc(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vandc(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vandc(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a & ~(vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_vandc(vector signed long long __a, vector signed long long __b) {
+ return __a & ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vandc(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a & ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vandc(vector signed long long __a, vector bool long long __b) {
+ return __a & ~(vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vandc(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a & ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vandc(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a & ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vandc(vector unsigned long long __a, vector bool long long __b) {
+ return __a & ~(vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_vandc(vector bool long long __a,
+ vector bool long long __b) {
+ return __a & ~__b;
+}
+#endif
+
/* vec_avg */
-static vector signed char __ATTRS_o_ai
-vec_avg(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_avg(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vavgsb(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_avg(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_avg(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vavgub(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_avg(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_avg(vector short __a, vector short __b) {
return __builtin_altivec_vavgsh(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_avg(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_avg(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vavguh(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_avg(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_avg(vector int __a, vector int __b) {
return __builtin_altivec_vavgsw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_avg(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_avg(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vavguw(__a, __b);
}
/* vec_vavgsb */
static vector signed char __attribute__((__always_inline__))
-vec_vavgsb(vector signed char __a, vector signed char __b)
-{
+vec_vavgsb(vector signed char __a, vector signed char __b) {
return __builtin_altivec_vavgsb(__a, __b);
}
/* vec_vavgub */
static vector unsigned char __attribute__((__always_inline__))
-vec_vavgub(vector unsigned char __a, vector unsigned char __b)
-{
+vec_vavgub(vector unsigned char __a, vector unsigned char __b) {
return __builtin_altivec_vavgub(__a, __b);
}
/* vec_vavgsh */
static vector short __attribute__((__always_inline__))
-vec_vavgsh(vector short __a, vector short __b)
-{
+vec_vavgsh(vector short __a, vector short __b) {
return __builtin_altivec_vavgsh(__a, __b);
}
/* vec_vavguh */
static vector unsigned short __attribute__((__always_inline__))
-vec_vavguh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vavguh(vector unsigned short __a, vector unsigned short __b) {
return __builtin_altivec_vavguh(__a, __b);
}
/* vec_vavgsw */
static vector int __attribute__((__always_inline__))
-vec_vavgsw(vector int __a, vector int __b)
-{
+vec_vavgsw(vector int __a, vector int __b) {
return __builtin_altivec_vavgsw(__a, __b);
}
/* vec_vavguw */
static vector unsigned int __attribute__((__always_inline__))
-vec_vavguw(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vavguw(vector unsigned int __a, vector unsigned int __b) {
return __builtin_altivec_vavguw(__a, __b);
}
/* vec_ceil */
-static vector float __attribute__((__always_inline__))
-vec_ceil(vector float __a)
-{
+static vector float __ATTRS_o_ai vec_ceil(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvrspip(__a);
+#else
return __builtin_altivec_vrfip(__a);
+#endif
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_ceil(vector double __a) {
+ return __builtin_vsx_xvrdpip(__a);
}
+#endif
/* vec_vrfip */
static vector float __attribute__((__always_inline__))
-vec_vrfip(vector float __a)
-{
+vec_vrfip(vector float __a) {
return __builtin_altivec_vrfip(__a);
}
/* vec_cmpb */
static vector int __attribute__((__always_inline__))
-vec_cmpb(vector float __a, vector float __b)
-{
+vec_cmpb(vector float __a, vector float __b) {
return __builtin_altivec_vcmpbfp(__a, __b);
}
/* vec_vcmpbfp */
static vector int __attribute__((__always_inline__))
-vec_vcmpbfp(vector float __a, vector float __b)
-{
+vec_vcmpbfp(vector float __a, vector float __b) {
return __builtin_altivec_vcmpbfp(__a, __b);
}
/* vec_cmpeq */
-static vector bool char __ATTRS_o_ai
-vec_cmpeq(vector signed char __a, vector signed char __b)
-{
- return (vector bool char)
- __builtin_altivec_vcmpequb((vector char)__a, (vector char)__b);
+static vector bool char __ATTRS_o_ai vec_cmpeq(vector signed char __a,
+ vector signed char __b) {
+ return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a,
+ (vector char)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_cmpeq(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector bool char)
- __builtin_altivec_vcmpequb((vector char)__a, (vector char)__b);
+static vector bool char __ATTRS_o_ai vec_cmpeq(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a,
+ (vector char)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_cmpeq(vector short __a, vector short __b)
-{
+static vector bool short __ATTRS_o_ai vec_cmpeq(vector short __a,
+ vector short __b) {
return (vector bool short)__builtin_altivec_vcmpequh(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_cmpeq(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector bool short)
- __builtin_altivec_vcmpequh((vector short)__a, (vector short)__b);
+static vector bool short __ATTRS_o_ai vec_cmpeq(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vcmpequh((vector short)__a,
+ (vector short)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpeq(vector int __a, vector int __b)
-{
+static vector bool int __ATTRS_o_ai vec_cmpeq(vector int __a, vector int __b) {
return (vector bool int)__builtin_altivec_vcmpequw(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpeq(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector bool int)
- __builtin_altivec_vcmpequw((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_cmpeq(vector unsigned int __a,
+ vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vcmpequw((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpeq(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector signed long long __a, vector signed long long __b) {
+ return (vector bool long long)__builtin_altivec_vcmpequd(__a, __b);
+}
+
+static vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector bool long long)__builtin_altivec_vcmpequd(
+ (vector long long)__a, (vector long long)__b);
+}
+#endif
+
+static vector bool int __ATTRS_o_ai vec_cmpeq(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return (vector bool int)__builtin_vsx_xvcmpeqsp(__a, __b);
+#else
return (vector bool int)__builtin_altivec_vcmpeqfp(__a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector double __a, vector double __b) {
+ return (vector bool long long)__builtin_vsx_xvcmpeqdp(__a, __b);
}
+#endif
/* vec_cmpge */
-static vector bool int __attribute__((__always_inline__))
-vec_cmpge(vector float __a, vector float __b)
-{
+static vector bool int __ATTRS_o_ai
+vec_cmpge(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return (vector bool int)__builtin_vsx_xvcmpgesp(__a, __b);
+#else
return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector double __a, vector double __b) {
+ return (vector bool long long)__builtin_vsx_xvcmpgedp(__a, __b);
+}
+#endif
+
+#ifdef __POWER8_VECTOR__
+/* Forwrad declarations as the functions are used here */
+static vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b);
+static vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector signed long long __a, vector signed long long __b);
+
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector signed long long __a, vector signed long long __b) {
+ return ~(vec_cmpgt(__b, __a));
}
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector unsigned long long __a, vector unsigned long long __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+#endif
+
/* vec_vcmpgefp */
static vector bool int __attribute__((__always_inline__))
-vec_vcmpgefp(vector float __a, vector float __b)
-{
+vec_vcmpgefp(vector float __a, vector float __b) {
return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
}
/* vec_cmpgt */
-static vector bool char __ATTRS_o_ai
-vec_cmpgt(vector signed char __a, vector signed char __b)
-{
+static vector bool char __ATTRS_o_ai vec_cmpgt(vector signed char __a,
+ vector signed char __b) {
return (vector bool char)__builtin_altivec_vcmpgtsb(__a, __b);
}
-static vector bool char __ATTRS_o_ai
-vec_cmpgt(vector unsigned char __a, vector unsigned char __b)
-{
+static vector bool char __ATTRS_o_ai vec_cmpgt(vector unsigned char __a,
+ vector unsigned char __b) {
return (vector bool char)__builtin_altivec_vcmpgtub(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_cmpgt(vector short __a, vector short __b)
-{
+static vector bool short __ATTRS_o_ai vec_cmpgt(vector short __a,
+ vector short __b) {
return (vector bool short)__builtin_altivec_vcmpgtsh(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_cmpgt(vector unsigned short __a, vector unsigned short __b)
-{
+static vector bool short __ATTRS_o_ai vec_cmpgt(vector unsigned short __a,
+ vector unsigned short __b) {
return (vector bool short)__builtin_altivec_vcmpgtuh(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpgt(vector int __a, vector int __b)
-{
+static vector bool int __ATTRS_o_ai vec_cmpgt(vector int __a, vector int __b) {
return (vector bool int)__builtin_altivec_vcmpgtsw(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpgt(vector unsigned int __a, vector unsigned int __b)
-{
+static vector bool int __ATTRS_o_ai vec_cmpgt(vector unsigned int __a,
+ vector unsigned int __b) {
return (vector bool int)__builtin_altivec_vcmpgtuw(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_cmpgt(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector signed long long __a, vector signed long long __b) {
+ return (vector bool long long)__builtin_altivec_vcmpgtsd(__a, __b);
+}
+
+static vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector bool long long)__builtin_altivec_vcmpgtud(__a, __b);
+}
+#endif
+
+static vector bool int __ATTRS_o_ai vec_cmpgt(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return (vector bool int)__builtin_vsx_xvcmpgtsp(__a, __b);
+#else
return (vector bool int)__builtin_altivec_vcmpgtfp(__a, __b);
+#endif
}
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector double __a, vector double __b) {
+ return (vector bool long long)__builtin_vsx_xvcmpgtdp(__a, __b);
+}
+#endif
/* vec_vcmpgtsb */
static vector bool char __attribute__((__always_inline__))
-vec_vcmpgtsb(vector signed char __a, vector signed char __b)
-{
+vec_vcmpgtsb(vector signed char __a, vector signed char __b) {
return (vector bool char)__builtin_altivec_vcmpgtsb(__a, __b);
}
/* vec_vcmpgtub */
static vector bool char __attribute__((__always_inline__))
-vec_vcmpgtub(vector unsigned char __a, vector unsigned char __b)
-{
+vec_vcmpgtub(vector unsigned char __a, vector unsigned char __b) {
return (vector bool char)__builtin_altivec_vcmpgtub(__a, __b);
}
/* vec_vcmpgtsh */
static vector bool short __attribute__((__always_inline__))
-vec_vcmpgtsh(vector short __a, vector short __b)
-{
+vec_vcmpgtsh(vector short __a, vector short __b) {
return (vector bool short)__builtin_altivec_vcmpgtsh(__a, __b);
}
/* vec_vcmpgtuh */
static vector bool short __attribute__((__always_inline__))
-vec_vcmpgtuh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vcmpgtuh(vector unsigned short __a, vector unsigned short __b) {
return (vector bool short)__builtin_altivec_vcmpgtuh(__a, __b);
}
/* vec_vcmpgtsw */
static vector bool int __attribute__((__always_inline__))
-vec_vcmpgtsw(vector int __a, vector int __b)
-{
+vec_vcmpgtsw(vector int __a, vector int __b) {
return (vector bool int)__builtin_altivec_vcmpgtsw(__a, __b);
}
/* vec_vcmpgtuw */
static vector bool int __attribute__((__always_inline__))
-vec_vcmpgtuw(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vcmpgtuw(vector unsigned int __a, vector unsigned int __b) {
return (vector bool int)__builtin_altivec_vcmpgtuw(__a, __b);
}
/* vec_vcmpgtfp */
static vector bool int __attribute__((__always_inline__))
-vec_vcmpgtfp(vector float __a, vector float __b)
-{
+vec_vcmpgtfp(vector float __a, vector float __b) {
return (vector bool int)__builtin_altivec_vcmpgtfp(__a, __b);
}
/* vec_cmple */
-static vector bool int __attribute__((__always_inline__))
-vec_cmple(vector float __a, vector float __b)
-{
- return (vector bool int)__builtin_altivec_vcmpgefp(__b, __a);
+static vector bool int __ATTRS_o_ai
+vec_cmple(vector float __a, vector float __b) {
+ return vec_cmpge(__b, __a);
}
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmple(vector double __a, vector double __b) {
+ return vec_cmpge(__b, __a);
+}
+#endif
+
+#ifdef __POWER8_VECTOR__
+static vector bool long long __ATTRS_o_ai
+vec_cmple(vector signed long long __a, vector signed long long __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool long long __ATTRS_o_ai
+vec_cmple(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_cmpge(__b, __a);
+}
+#endif
+
/* vec_cmplt */
-static vector bool char __ATTRS_o_ai
-vec_cmplt(vector signed char __a, vector signed char __b)
-{
- return (vector bool char)__builtin_altivec_vcmpgtsb(__b, __a);
+static vector bool char __ATTRS_o_ai vec_cmplt(vector signed char __a,
+ vector signed char __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool char __ATTRS_o_ai
-vec_cmplt(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector bool char)__builtin_altivec_vcmpgtub(__b, __a);
+static vector bool char __ATTRS_o_ai vec_cmplt(vector unsigned char __a,
+ vector unsigned char __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool short __ATTRS_o_ai
-vec_cmplt(vector short __a, vector short __b)
-{
- return (vector bool short)__builtin_altivec_vcmpgtsh(__b, __a);
+static vector bool short __ATTRS_o_ai vec_cmplt(vector short __a,
+ vector short __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool short __ATTRS_o_ai
-vec_cmplt(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector bool short)__builtin_altivec_vcmpgtuh(__b, __a);
+static vector bool short __ATTRS_o_ai vec_cmplt(vector unsigned short __a,
+ vector unsigned short __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool int __ATTRS_o_ai
-vec_cmplt(vector int __a, vector int __b)
-{
- return (vector bool int)__builtin_altivec_vcmpgtsw(__b, __a);
+static vector bool int __ATTRS_o_ai vec_cmplt(vector int __a, vector int __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool int __ATTRS_o_ai
-vec_cmplt(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector bool int)__builtin_altivec_vcmpgtuw(__b, __a);
+static vector bool int __ATTRS_o_ai vec_cmplt(vector unsigned int __a,
+ vector unsigned int __b) {
+ return vec_cmpgt(__b, __a);
}
-static vector bool int __ATTRS_o_ai
-vec_cmplt(vector float __a, vector float __b)
-{
- return (vector bool int)__builtin_altivec_vcmpgtfp(__b, __a);
+static vector bool int __ATTRS_o_ai vec_cmplt(vector float __a,
+ vector float __b) {
+ return vec_cmpgt(__b, __a);
+}
+
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmplt(vector double __a, vector double __b) {
+ return vec_cmpgt(__b, __a);
+}
+#endif
+
+#ifdef __POWER8_VECTOR__
+static vector bool long long __ATTRS_o_ai
+vec_cmplt(vector signed long long __a, vector signed long long __b) {
+ return vec_cmpgt(__b, __a);
}
+static vector bool long long __ATTRS_o_ai
+vec_cmplt(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_cmpgt(__b, __a);
+}
+
+/* vec_cntlz */
+
+static vector signed char __ATTRS_o_ai vec_cntlz(vector signed char __a) {
+ return __builtin_altivec_vclzb(__a);
+}
+static vector unsigned char __ATTRS_o_ai vec_cntlz(vector unsigned char __a) {
+ return __builtin_altivec_vclzb(__a);
+}
+static vector signed short __ATTRS_o_ai vec_cntlz(vector signed short __a) {
+ return __builtin_altivec_vclzh(__a);
+}
+static vector unsigned short __ATTRS_o_ai vec_cntlz(vector unsigned short __a) {
+ return __builtin_altivec_vclzh(__a);
+}
+static vector signed int __ATTRS_o_ai vec_cntlz(vector signed int __a) {
+ return __builtin_altivec_vclzw(__a);
+}
+static vector unsigned int __ATTRS_o_ai vec_cntlz(vector unsigned int __a) {
+ return __builtin_altivec_vclzw(__a);
+}
+static vector signed long long __ATTRS_o_ai
+vec_cntlz(vector signed long long __a) {
+ return __builtin_altivec_vclzd(__a);
+}
+static vector unsigned long long __ATTRS_o_ai
+vec_cntlz(vector unsigned long long __a) {
+ return __builtin_altivec_vclzd(__a);
+}
+#endif
+
+/* vec_cpsgn */
+
+#ifdef __VSX__
+static vector float __ATTRS_o_ai vec_cpsgn(vector float __a, vector float __b) {
+ return __builtin_vsx_xvcpsgnsp(__a, __b);
+}
+
+static vector double __ATTRS_o_ai vec_cpsgn(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcpsgndp(__a, __b);
+}
+#endif
+
/* vec_ctf */
-static vector float __ATTRS_o_ai
-vec_ctf(vector int __a, int __b)
-{
+static vector float __ATTRS_o_ai vec_ctf(vector int __a, int __b) {
return __builtin_altivec_vcfsx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_ctf(vector unsigned int __a, int __b)
-{
+static vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, int __b) {
return __builtin_altivec_vcfux((vector int)__a, __b);
}
/* vec_vcfsx */
static vector float __attribute__((__always_inline__))
-vec_vcfsx(vector int __a, int __b)
-{
+vec_vcfsx(vector int __a, int __b) {
return __builtin_altivec_vcfsx(__a, __b);
}
/* vec_vcfux */
static vector float __attribute__((__always_inline__))
-vec_vcfux(vector unsigned int __a, int __b)
-{
+vec_vcfux(vector unsigned int __a, int __b) {
return __builtin_altivec_vcfux((vector int)__a, __b);
}
/* vec_cts */
static vector int __attribute__((__always_inline__))
-vec_cts(vector float __a, int __b)
-{
+vec_cts(vector float __a, int __b) {
return __builtin_altivec_vctsxs(__a, __b);
}
/* vec_vctsxs */
static vector int __attribute__((__always_inline__))
-vec_vctsxs(vector float __a, int __b)
-{
+vec_vctsxs(vector float __a, int __b) {
return __builtin_altivec_vctsxs(__a, __b);
}
/* vec_ctu */
static vector unsigned int __attribute__((__always_inline__))
-vec_ctu(vector float __a, int __b)
-{
+vec_ctu(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __b);
}
/* vec_vctuxs */
static vector unsigned int __attribute__((__always_inline__))
-vec_vctuxs(vector float __a, int __b)
-{
+vec_vctuxs(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __b);
}
/* vec_div */
+
+/* Integer vector divides (vectors are scalarized, elements divided
+ and the vectors reassembled).
+*/
+static vector signed char __ATTRS_o_ai vec_div(vector signed char __a,
+ vector signed char __b) {
+ return __a / __b;
+}
+
+static vector unsigned char __ATTRS_o_ai vec_div(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __a / __b;
+}
+
+static vector signed short __ATTRS_o_ai vec_div(vector signed short __a,
+ vector signed short __b) {
+ return __a / __b;
+}
+
+static vector unsigned short __ATTRS_o_ai vec_div(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __a / __b;
+}
+
+static vector signed int __ATTRS_o_ai vec_div(vector signed int __a,
+ vector signed int __b) {
+ return __a / __b;
+}
+
+static vector unsigned int __ATTRS_o_ai vec_div(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __a / __b;
+}
+
#ifdef __VSX__
-static vector float __ATTRS_o_ai
-vec_div(vector float __a, vector float __b)
-{
- return __builtin_vsx_xvdivsp(__a, __b);
+static vector signed long long __ATTRS_o_ai
+vec_div(vector signed long long __a, vector signed long long __b) {
+ return __a / __b;
}
-static vector double __ATTRS_o_ai
-vec_div(vector double __a, vector double __b)
-{
- return __builtin_vsx_xvdivdp(__a, __b);
+static vector unsigned long long __ATTRS_o_ai
+vec_div(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a / __b;
+}
+
+static vector float __ATTRS_o_ai vec_div(vector float __a, vector float __b) {
+ return __a / __b;
+}
+
+static vector double __ATTRS_o_ai vec_div(vector double __a,
+ vector double __b) {
+ return __a / __b;
}
#endif
/* vec_dss */
-static void __attribute__((__always_inline__))
-vec_dss(int __a)
-{
+static void __attribute__((__always_inline__)) vec_dss(int __a) {
__builtin_altivec_dss(__a);
}
/* vec_dssall */
-static void __attribute__((__always_inline__))
-vec_dssall(void)
-{
+static void __attribute__((__always_inline__)) vec_dssall(void) {
__builtin_altivec_dssall();
}
/* vec_dst */
static void __attribute__((__always_inline__))
-vec_dst(const void *__a, int __b, int __c)
-{
+vec_dst(const void *__a, int __b, int __c) {
__builtin_altivec_dst(__a, __b, __c);
}
/* vec_dstst */
static void __attribute__((__always_inline__))
-vec_dstst(const void *__a, int __b, int __c)
-{
+vec_dstst(const void *__a, int __b, int __c) {
__builtin_altivec_dstst(__a, __b, __c);
}
/* vec_dststt */
static void __attribute__((__always_inline__))
-vec_dststt(const void *__a, int __b, int __c)
-{
+vec_dststt(const void *__a, int __b, int __c) {
__builtin_altivec_dststt(__a, __b, __c);
}
/* vec_dstt */
static void __attribute__((__always_inline__))
-vec_dstt(const void *__a, int __b, int __c)
-{
+vec_dstt(const void *__a, int __b, int __c) {
__builtin_altivec_dstt(__a, __b, __c);
}
+/* vec_eqv */
+
+#ifdef __POWER8_VECTOR__
+static vector signed char __ATTRS_o_ai vec_eqv(vector signed char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed char __ATTRS_o_ai vec_eqv(vector bool char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed char __ATTRS_o_ai vec_eqv(vector signed char __a,
+ vector bool char __b) {
+ return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_eqv(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_eqv(vector bool char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_eqv(vector unsigned char __a,
+ vector bool char __b) {
+ return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a,
+ vector signed short __b) {
+ return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed short __ATTRS_o_ai vec_eqv(vector bool short __a,
+ vector signed short __b) {
+ return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a,
+ vector bool short __b) {
+ return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned short __ATTRS_o_ai vec_eqv(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned short __ATTRS_o_ai vec_eqv(vector bool short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned short __ATTRS_o_ai vec_eqv(vector unsigned short __a,
+ vector bool short __b) {
+ return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed int __ATTRS_o_ai vec_eqv(vector signed int __a,
+ vector signed int __b) {
+ return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed int __ATTRS_o_ai vec_eqv(vector bool int __a,
+ vector signed int __b) {
+ return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed int __ATTRS_o_ai vec_eqv(vector signed int __a,
+ vector bool int __b) {
+ return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_eqv(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_eqv(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_eqv(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_eqv(vector signed long long __a, vector signed long long __b) {
+ return (vector signed long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_eqv(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_eqv(vector signed long long __a, vector bool long long __b) {
+ return (vector signed long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_eqv(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_eqv(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_eqv(vector unsigned long long __a, vector bool long long __b) {
+ return (vector unsigned long long)
+ __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
+}
+
+static vector float __ATTRS_o_ai vec_eqv(vector float __a, vector float __b) {
+ return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector float __ATTRS_o_ai vec_eqv(vector bool int __a,
+ vector float __b) {
+ return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector float __ATTRS_o_ai vec_eqv(vector float __a,
+ vector bool int __b) {
+ return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector double __ATTRS_o_ai vec_eqv(vector double __a,
+ vector double __b) {
+ return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector double __ATTRS_o_ai vec_eqv(vector bool long long __a,
+ vector double __b) {
+ return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
+static vector double __ATTRS_o_ai vec_eqv(vector double __a,
+ vector bool long long __b) {
+ return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+#endif
+
/* vec_expte */
static vector float __attribute__((__always_inline__))
-vec_expte(vector float __a)
-{
+vec_expte(vector float __a) {
return __builtin_altivec_vexptefp(__a);
}
/* vec_vexptefp */
static vector float __attribute__((__always_inline__))
-vec_vexptefp(vector float __a)
-{
+vec_vexptefp(vector float __a) {
return __builtin_altivec_vexptefp(__a);
}
/* vec_floor */
-static vector float __attribute__((__always_inline__))
-vec_floor(vector float __a)
-{
+static vector float __ATTRS_o_ai vec_floor(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvrspim(__a);
+#else
return __builtin_altivec_vrfim(__a);
+#endif
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_floor(vector double __a) {
+ return __builtin_vsx_xvrdpim(__a);
+}
+#endif
+
/* vec_vrfim */
static vector float __attribute__((__always_inline__))
-vec_vrfim(vector float __a)
-{
+vec_vrfim(vector float __a) {
return __builtin_altivec_vrfim(__a);
}
/* vec_ld */
-static vector signed char __ATTRS_o_ai
-vec_ld(int __a, const vector signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_ld(int __a,
+ const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_ld(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_ld(int __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static vector unsigned char __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned char *__b)
-{
+vec_ld(int __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_ld(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_ld(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
-static vector bool char __ATTRS_o_ai
-vec_ld(int __a, const vector bool char *__b)
-{
+static vector bool char __ATTRS_o_ai vec_ld(int __a,
+ const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvx(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_ld(int __a, const vector short *__b)
-{
+static vector short __ATTRS_o_ai vec_ld(int __a, const vector short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_ld(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_ld(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned short *__b)
-{
+vec_ld(int __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_ld(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_ld(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_ld(int __a, const vector bool short *__b)
-{
+static vector bool short __ATTRS_o_ai vec_ld(int __a,
+ const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvx(__a, __b);
}
-static vector pixel __ATTRS_o_ai
-vec_ld(int __a, const vector pixel *__b)
-{
+static vector pixel __ATTRS_o_ai vec_ld(int __a, const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvx(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_ld(int __a, const vector int *__b)
-{
+static vector int __ATTRS_o_ai vec_ld(int __a, const vector int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_ld(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_ld(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_ld(int __a,
+ const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_ld(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_ld(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_ld(int __a, const vector bool int *__b)
-{
+static vector bool int __ATTRS_o_ai vec_ld(int __a,
+ const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_ld(int __a, const vector float *__b)
-{
+static vector float __ATTRS_o_ai vec_ld(int __a, const vector float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_ld(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_ld(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
/* vec_lvx */
-static vector signed char __ATTRS_o_ai
-vec_lvx(int __a, const vector signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lvx(int __a,
+ const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_lvx(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lvx(int __a,
+ const signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static vector unsigned char __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned char *__b)
-{
+vec_lvx(int __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvx(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvx(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
-static vector bool char __ATTRS_o_ai
-vec_lvx(int __a, const vector bool char *__b)
-{
+static vector bool char __ATTRS_o_ai vec_lvx(int __a,
+ const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvx(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_lvx(int __a, const vector short *__b)
-{
+static vector short __ATTRS_o_ai vec_lvx(int __a, const vector short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_lvx(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_lvx(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned short *__b)
-{
+vec_lvx(int __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvx(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_lvx(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_lvx(int __a, const vector bool short *__b)
-{
+static vector bool short __ATTRS_o_ai vec_lvx(int __a,
+ const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvx(__a, __b);
}
-static vector pixel __ATTRS_o_ai
-vec_lvx(int __a, const vector pixel *__b)
-{
+static vector pixel __ATTRS_o_ai vec_lvx(int __a, const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvx(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_lvx(int __a, const vector int *__b)
-{
+static vector int __ATTRS_o_ai vec_lvx(int __a, const vector int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_lvx(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_lvx(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
static vector unsigned int __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned int *__b)
-{
+vec_lvx(int __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvx(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_lvx(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_lvx(int __a, const vector bool int *__b)
-{
+static vector bool int __ATTRS_o_ai vec_lvx(int __a,
+ const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lvx(int __a, const vector float *__b)
-{
+static vector float __ATTRS_o_ai vec_lvx(int __a, const vector float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lvx(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_lvx(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
/* vec_lde */
-static vector signed char __ATTRS_o_ai
-vec_lde(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lde(int __a,
+ const signed char *__b) {
return (vector signed char)__builtin_altivec_lvebx(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_lde(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lde(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvebx(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_lde(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_lde(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvehx(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_lde(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_lde(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvehx(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_lde(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_lde(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvewx(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_lde(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_lde(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvewx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lde(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_lde(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvewx(__a, __b);
}
/* vec_lvebx */
-static vector signed char __ATTRS_o_ai
-vec_lvebx(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lvebx(int __a,
+ const signed char *__b) {
return (vector signed char)__builtin_altivec_lvebx(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvebx(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvebx(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvebx(__a, __b);
}
/* vec_lvehx */
-static vector short __ATTRS_o_ai
-vec_lvehx(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_lvehx(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvehx(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvehx(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_lvehx(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvehx(__a, __b);
}
/* vec_lvewx */
-static vector int __ATTRS_o_ai
-vec_lvewx(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_lvewx(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvewx(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvewx(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_lvewx(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvewx(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lvewx(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_lvewx(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvewx(__a, __b);
}
/* vec_ldl */
-static vector signed char __ATTRS_o_ai
-vec_ldl(int __a, const vector signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_ldl(int __a,
+ const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_ldl(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_ldl(int __a,
+ const signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned char __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned char *__b)
-{
+vec_ldl(int __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_ldl(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_ldl(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool char __ATTRS_o_ai
-vec_ldl(int __a, const vector bool char *__b)
-{
+static vector bool char __ATTRS_o_ai vec_ldl(int __a,
+ const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvxl(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_ldl(int __a, const vector short *__b)
-{
+static vector short __ATTRS_o_ai vec_ldl(int __a, const vector short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_ldl(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_ldl(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned short *__b)
-{
+vec_ldl(int __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_ldl(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_ldl(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_ldl(int __a, const vector bool short *__b)
-{
+static vector bool short __ATTRS_o_ai vec_ldl(int __a,
+ const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvxl(__a, __b);
}
-static vector pixel __ATTRS_o_ai
-vec_ldl(int __a, const vector pixel *__b)
-{
+static vector pixel __ATTRS_o_ai vec_ldl(int __a, const vector pixel *__b) {
return (vector pixel short)__builtin_altivec_lvxl(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_ldl(int __a, const vector int *__b)
-{
+static vector int __ATTRS_o_ai vec_ldl(int __a, const vector int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_ldl(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_ldl(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned int __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned int *__b)
-{
+vec_ldl(int __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_ldl(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_ldl(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_ldl(int __a, const vector bool int *__b)
-{
+static vector bool int __ATTRS_o_ai vec_ldl(int __a,
+ const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvxl(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_ldl(int __a, const vector float *__b)
-{
+static vector float __ATTRS_o_ai vec_ldl(int __a, const vector float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_ldl(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_ldl(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
/* vec_lvxl */
-static vector signed char __ATTRS_o_ai
-vec_lvxl(int __a, const vector signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lvxl(int __a,
+ const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_lvxl(int __a, const signed char *__b)
-{
+static vector signed char __ATTRS_o_ai vec_lvxl(int __a,
+ const signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned char __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned char *__b)
-{
+vec_lvxl(int __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvxl(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool char __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool char *__b)
-{
+static vector bool char __ATTRS_o_ai vec_lvxl(int __a,
+ const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvxl(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_lvxl(int __a, const vector short *__b)
-{
+static vector short __ATTRS_o_ai vec_lvxl(int __a, const vector short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_lvxl(int __a, const short *__b)
-{
+static vector short __ATTRS_o_ai vec_lvxl(int __a, const short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned short *__b)
-{
+vec_lvxl(int __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned short *__b)
-{
+static vector unsigned short __ATTRS_o_ai vec_lvxl(int __a,
+ const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool short __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool short *__b)
-{
+static vector bool short __ATTRS_o_ai vec_lvxl(int __a,
+ const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvxl(__a, __b);
}
-static vector pixel __ATTRS_o_ai
-vec_lvxl(int __a, const vector pixel *__b)
-{
+static vector pixel __ATTRS_o_ai vec_lvxl(int __a, const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvxl(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_lvxl(int __a, const vector int *__b)
-{
+static vector int __ATTRS_o_ai vec_lvxl(int __a, const vector int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_lvxl(int __a, const int *__b)
-{
+static vector int __ATTRS_o_ai vec_lvxl(int __a, const int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
static vector unsigned int __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned int *__b)
-{
+vec_lvxl(int __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned int *__b)
-{
+static vector unsigned int __ATTRS_o_ai vec_lvxl(int __a,
+ const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
-static vector bool int __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool int *__b)
-{
+static vector bool int __ATTRS_o_ai vec_lvxl(int __a,
+ const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvxl(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lvxl(int __a, const vector float *__b)
-{
+static vector float __ATTRS_o_ai vec_lvxl(int __a, const vector float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_lvxl(int __a, const float *__b)
-{
+static vector float __ATTRS_o_ai vec_lvxl(int __a, const float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
/* vec_loge */
static vector float __attribute__((__always_inline__))
-vec_loge(vector float __a)
-{
+vec_loge(vector float __a) {
return __builtin_altivec_vlogefp(__a);
}
/* vec_vlogefp */
static vector float __attribute__((__always_inline__))
-vec_vlogefp(vector float __a)
-{
+vec_vlogefp(vector float __a) {
return __builtin_altivec_vlogefp(__a);
}
@@ -2270,133 +2582,116 @@ vec_vlogefp(vector float __a)
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const signed char *__b)
-{
- vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const signed char *__b) {
+ vector unsigned char mask =
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const signed char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a,
+ const signed char *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const unsigned char *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const unsigned char *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const short *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const short *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const short *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const short *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const unsigned short *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const unsigned short *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const unsigned short *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a,
+ const unsigned short *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const int *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const int *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const int *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const int *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const unsigned int *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const unsigned int *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const unsigned int *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a,
+ const unsigned int *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsl(int __a, const float *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsl(int __a, const float *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsl(int __a, const float *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const float *__b) {
return (vector unsigned char)__builtin_altivec_lvsl(__a, __b);
}
#endif
@@ -2405,283 +2700,295 @@ vec_lvsl(int __a, const float *__b)
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const signed char *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const signed char *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const signed char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a,
+ const signed char *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const unsigned char *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const unsigned char *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const unsigned char *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a,
+ const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const short *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const short *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const short *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const short *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const unsigned short *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const unsigned short *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const unsigned short *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a,
+ const unsigned short *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const int *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const int *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const int *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const int *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const unsigned int *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const unsigned int *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const unsigned int *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a,
+ const unsigned int *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
#ifdef __LITTLE_ENDIAN__
static vector unsigned char __ATTRS_o_ai
-__attribute__((deprecated("use assignment for unaligned little endian \
-loads/stores")))
-vec_lvsr(int __a, const float *__b)
-{
+ __attribute__((__deprecated__("use assignment for unaligned little endian \
+loads/stores"))) vec_lvsr(int __a, const float *__b) {
vector unsigned char mask =
- (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
- vector unsigned char reverse = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+ (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
+ vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(mask, mask, reverse);
}
#else
-static vector unsigned char __ATTRS_o_ai
-vec_lvsr(int __a, const float *__b)
-{
+static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const float *__b) {
return (vector unsigned char)__builtin_altivec_lvsr(__a, __b);
}
#endif
/* vec_madd */
-static vector float __attribute__((__always_inline__))
-vec_madd(vector float __a, vector float __b, vector float __c)
-{
+static vector float __ATTRS_o_ai
+vec_madd(vector float __a, vector float __b, vector float __c) {
+#ifdef __VSX__
+ return __builtin_vsx_xvmaddasp(__a, __b, __c);
+#else
return __builtin_altivec_vmaddfp(__a, __b, __c);
+#endif
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_madd(vector double __a, vector double __b, vector double __c) {
+ return __builtin_vsx_xvmaddadp(__a, __b, __c);
+}
+#endif
+
/* vec_vmaddfp */
static vector float __attribute__((__always_inline__))
-vec_vmaddfp(vector float __a, vector float __b, vector float __c)
-{
+vec_vmaddfp(vector float __a, vector float __b, vector float __c) {
return __builtin_altivec_vmaddfp(__a, __b, __c);
}
/* vec_madds */
static vector signed short __attribute__((__always_inline__))
-vec_madds(vector signed short __a, vector signed short __b, vector signed short __c)
-{
+vec_madds(vector signed short __a, vector signed short __b,
+ vector signed short __c) {
return __builtin_altivec_vmhaddshs(__a, __b, __c);
}
/* vec_vmhaddshs */
static vector signed short __attribute__((__always_inline__))
-vec_vmhaddshs(vector signed short __a,
- vector signed short __b,
- vector signed short __c)
-{
+vec_vmhaddshs(vector signed short __a, vector signed short __b,
+ vector signed short __c) {
return __builtin_altivec_vmhaddshs(__a, __b, __c);
}
+/* vec_msub */
+
+#ifdef __VSX__
+static vector float __ATTRS_o_ai
+vec_msub(vector float __a, vector float __b, vector float __c) {
+ return __builtin_vsx_xvmsubasp(__a, __b, __c);
+}
+
+static vector double __ATTRS_o_ai
+vec_msub(vector double __a, vector double __b, vector double __c) {
+ return __builtin_vsx_xvmsubadp(__a, __b, __c);
+}
+#endif
+
/* vec_max */
-static vector signed char __ATTRS_o_ai
-vec_max(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_max(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vmaxsb(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_max(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_max(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vmaxsb((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_max(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_max(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vmaxsb(__a, (vector signed char)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_max(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_max(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vmaxub(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_max(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_max(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vmaxub((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_max(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_max(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vmaxub(__a, (vector unsigned char)__b);
}
-static vector short __ATTRS_o_ai
-vec_max(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_max(vector short __a, vector short __b) {
return __builtin_altivec_vmaxsh(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_max(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_max(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vmaxsh((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_max(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_max(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vmaxsh(__a, (vector short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_max(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_max(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vmaxuh(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_max(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_max(vector bool short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vmaxuh((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_max(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_max(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vmaxuh(__a, (vector unsigned short)__b);
}
-static vector int __ATTRS_o_ai
-vec_max(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_max(vector int __a, vector int __b) {
return __builtin_altivec_vmaxsw(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_max(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_max(vector bool int __a, vector int __b) {
return __builtin_altivec_vmaxsw((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_max(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_max(vector int __a, vector bool int __b) {
return __builtin_altivec_vmaxsw(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_max(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_max(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vmaxuw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_max(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_max(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vmaxuw((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_max(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_max(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vmaxuw(__a, (vector unsigned int)__b);
}
-static vector float __ATTRS_o_ai
-vec_max(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_max(vector signed long long __a, vector signed long long __b) {
+ return __builtin_altivec_vmaxsd(__a, __b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_max(vector bool long long __a, vector signed long long __b) {
+ return __builtin_altivec_vmaxsd((vector signed long long)__a, __b);
+}
+
+static vector signed long long __ATTRS_o_ai vec_max(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vmaxsd(__a, (vector signed long long)__b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_max(vector unsigned long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vmaxud(__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_max(vector bool long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vmaxud((vector unsigned long long)__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_max(vector unsigned long long __a, vector bool long long __b) {
+ return __builtin_altivec_vmaxud(__a, (vector unsigned long long)__b);
+}
+#endif
+
+static vector float __ATTRS_o_ai vec_max(vector float __a, vector float __b) {
#ifdef __VSX__
return __builtin_vsx_xvmaxsp(__a, __b);
#else
@@ -2690,138 +2997,115 @@ vec_max(vector float __a, vector float __b)
}
#ifdef __VSX__
-static vector double __ATTRS_o_ai
-vec_max(vector double __a, vector double __b)
-{
+static vector double __ATTRS_o_ai vec_max(vector double __a,
+ vector double __b) {
return __builtin_vsx_xvmaxdp(__a, __b);
}
#endif
/* vec_vmaxsb */
-static vector signed char __ATTRS_o_ai
-vec_vmaxsb(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vmaxsb(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vmaxsb(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vmaxsb(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vmaxsb(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vmaxsb((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vmaxsb(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vmaxsb(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vmaxsb(__a, (vector signed char)__b);
}
/* vec_vmaxub */
-static vector unsigned char __ATTRS_o_ai
-vec_vmaxub(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vmaxub(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vmaxub(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vmaxub(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vmaxub(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vmaxub((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vmaxub(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vmaxub(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vmaxub(__a, (vector unsigned char)__b);
}
/* vec_vmaxsh */
-static vector short __ATTRS_o_ai
-vec_vmaxsh(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vmaxsh(vector short __a,
+ vector short __b) {
return __builtin_altivec_vmaxsh(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vmaxsh(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vmaxsh(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vmaxsh((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vmaxsh(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vmaxsh(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vmaxsh(__a, (vector short)__b);
}
/* vec_vmaxuh */
static vector unsigned short __ATTRS_o_ai
-vec_vmaxuh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vmaxuh(vector unsigned short __a, vector unsigned short __b) {
return __builtin_altivec_vmaxuh(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_vmaxuh(vector bool short __a, vector unsigned short __b)
-{
+vec_vmaxuh(vector bool short __a, vector unsigned short __b) {
return __builtin_altivec_vmaxuh((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vmaxuh(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vmaxuh(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vmaxuh(__a, (vector unsigned short)__b);
}
/* vec_vmaxsw */
-static vector int __ATTRS_o_ai
-vec_vmaxsw(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vmaxsw(vector int __a, vector int __b) {
return __builtin_altivec_vmaxsw(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vmaxsw(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vmaxsw(vector bool int __a, vector int __b) {
return __builtin_altivec_vmaxsw((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vmaxsw(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vmaxsw(vector int __a, vector bool int __b) {
return __builtin_altivec_vmaxsw(__a, (vector int)__b);
}
/* vec_vmaxuw */
-static vector unsigned int __ATTRS_o_ai
-vec_vmaxuw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vmaxuw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vmaxuw(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vmaxuw((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vmaxuw(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vmaxuw(__a, (vector unsigned int)__b);
}
/* vec_vmaxfp */
static vector float __attribute__((__always_inline__))
-vec_vmaxfp(vector float __a, vector float __b)
-{
+vec_vmaxfp(vector float __a, vector float __b) {
#ifdef __VSX__
return __builtin_vsx_xvmaxsp(__a, __b);
#else
@@ -2831,505 +3115,713 @@ vec_vmaxfp(vector float __a, vector float __b)
/* vec_mergeh */
-static vector signed char __ATTRS_o_ai
-vec_mergeh(vector signed char __a, vector signed char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector signed char __ATTRS_o_ai vec_mergeh(vector signed char __a,
+ vector signed char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
-static vector unsigned char __ATTRS_o_ai
-vec_mergeh(vector unsigned char __a, vector unsigned char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector unsigned char __ATTRS_o_ai vec_mergeh(vector unsigned char __a,
+ vector unsigned char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
-static vector bool char __ATTRS_o_ai
-vec_mergeh(vector bool char __a, vector bool char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector bool char __ATTRS_o_ai vec_mergeh(vector bool char __a,
+ vector bool char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
-static vector short __ATTRS_o_ai
-vec_mergeh(vector short __a, vector short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector short __ATTRS_o_ai vec_mergeh(vector short __a,
+ vector short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
static vector unsigned short __ATTRS_o_ai
-vec_mergeh(vector unsigned short __a, vector unsigned short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+vec_mergeh(vector unsigned short __a, vector unsigned short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
-static vector bool short __ATTRS_o_ai
-vec_mergeh(vector bool short __a, vector bool short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector bool short __ATTRS_o_ai vec_mergeh(vector bool short __a,
+ vector bool short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
-static vector pixel __ATTRS_o_ai
-vec_mergeh(vector pixel __a, vector pixel __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector pixel __ATTRS_o_ai vec_mergeh(vector pixel __a,
+ vector pixel __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
-static vector int __ATTRS_o_ai
-vec_mergeh(vector int __a, vector int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector int __ATTRS_o_ai vec_mergeh(vector int __a, vector int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector unsigned int __ATTRS_o_ai
-vec_mergeh(vector unsigned int __a, vector unsigned int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector unsigned int __ATTRS_o_ai vec_mergeh(vector unsigned int __a,
+ vector unsigned int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector bool int __ATTRS_o_ai
-vec_mergeh(vector bool int __a, vector bool int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector bool int __ATTRS_o_ai vec_mergeh(vector bool int __a,
+ vector bool int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector float __ATTRS_o_ai
-vec_mergeh(vector float __a, vector float __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector float __ATTRS_o_ai vec_mergeh(vector float __a,
+ vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_mergeh(vector signed long long __a, vector signed long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_mergeh(vector signed long long __a, vector bool long long __b) {
+ return vec_perm(__a, (vector signed long long)__b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_mergeh(vector bool long long __a, vector signed long long __b) {
+ return vec_perm((vector signed long long)__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_mergeh(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
}
+static vector unsigned long long __ATTRS_o_ai
+vec_mergeh(vector unsigned long long __a, vector bool long long __b) {
+ return vec_perm(__a, (vector unsigned long long)__b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_mergeh(vector bool long long __a, vector unsigned long long __b) {
+ return vec_perm((vector unsigned long long)__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+static vector double __ATTRS_o_ai vec_mergeh(vector double __a,
+ vector double __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+static vector double __ATTRS_o_ai vec_mergeh(vector double __a,
+ vector bool long long __b) {
+ return vec_perm(__a, (vector double)__b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+static vector double __ATTRS_o_ai vec_mergeh(vector bool long long __a,
+ vector double __b) {
+ return vec_perm((vector double)__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+#endif
+
/* vec_vmrghb */
#define __builtin_altivec_vmrghb vec_vmrghb
-static vector signed char __ATTRS_o_ai
-vec_vmrghb(vector signed char __a, vector signed char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector signed char __ATTRS_o_ai vec_vmrghb(vector signed char __a,
+ vector signed char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
-static vector unsigned char __ATTRS_o_ai
-vec_vmrghb(vector unsigned char __a, vector unsigned char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector unsigned char __ATTRS_o_ai vec_vmrghb(vector unsigned char __a,
+ vector unsigned char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
-static vector bool char __ATTRS_o_ai
-vec_vmrghb(vector bool char __a, vector bool char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+static vector bool char __ATTRS_o_ai vec_vmrghb(vector bool char __a,
+ vector bool char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12,
+ 0x03, 0x13, 0x04, 0x14, 0x05, 0x15,
+ 0x06, 0x16, 0x07, 0x17));
}
/* vec_vmrghh */
#define __builtin_altivec_vmrghh vec_vmrghh
-static vector short __ATTRS_o_ai
-vec_vmrghh(vector short __a, vector short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector short __ATTRS_o_ai vec_vmrghh(vector short __a,
+ vector short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
static vector unsigned short __ATTRS_o_ai
-vec_vmrghh(vector unsigned short __a, vector unsigned short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+vec_vmrghh(vector unsigned short __a, vector unsigned short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
-static vector bool short __ATTRS_o_ai
-vec_vmrghh(vector bool short __a, vector bool short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector bool short __ATTRS_o_ai vec_vmrghh(vector bool short __a,
+ vector bool short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
-static vector pixel __ATTRS_o_ai
-vec_vmrghh(vector pixel __a, vector pixel __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+static vector pixel __ATTRS_o_ai vec_vmrghh(vector pixel __a,
+ vector pixel __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03,
+ 0x12, 0x13, 0x04, 0x05, 0x14, 0x15,
+ 0x06, 0x07, 0x16, 0x17));
}
/* vec_vmrghw */
#define __builtin_altivec_vmrghw vec_vmrghw
-static vector int __ATTRS_o_ai
-vec_vmrghw(vector int __a, vector int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector int __ATTRS_o_ai vec_vmrghw(vector int __a, vector int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector unsigned int __ATTRS_o_ai
-vec_vmrghw(vector unsigned int __a, vector unsigned int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector unsigned int __ATTRS_o_ai vec_vmrghw(vector unsigned int __a,
+ vector unsigned int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector bool int __ATTRS_o_ai
-vec_vmrghw(vector bool int __a, vector bool int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector bool int __ATTRS_o_ai vec_vmrghw(vector bool int __a,
+ vector bool int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
-static vector float __ATTRS_o_ai
-vec_vmrghw(vector float __a, vector float __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+static vector float __ATTRS_o_ai vec_vmrghw(vector float __a,
+ vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17));
}
/* vec_mergel */
-static vector signed char __ATTRS_o_ai
-vec_mergel(vector signed char __a, vector signed char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector signed char __ATTRS_o_ai vec_mergel(vector signed char __a,
+ vector signed char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
-static vector unsigned char __ATTRS_o_ai
-vec_mergel(vector unsigned char __a, vector unsigned char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector unsigned char __ATTRS_o_ai vec_mergel(vector unsigned char __a,
+ vector unsigned char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
-static vector bool char __ATTRS_o_ai
-vec_mergel(vector bool char __a, vector bool char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector bool char __ATTRS_o_ai vec_mergel(vector bool char __a,
+ vector bool char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
-static vector short __ATTRS_o_ai
-vec_mergel(vector short __a, vector short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector short __ATTRS_o_ai vec_mergel(vector short __a,
+ vector short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
static vector unsigned short __ATTRS_o_ai
-vec_mergel(vector unsigned short __a, vector unsigned short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+vec_mergel(vector unsigned short __a, vector unsigned short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
-static vector bool short __ATTRS_o_ai
-vec_mergel(vector bool short __a, vector bool short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector bool short __ATTRS_o_ai vec_mergel(vector bool short __a,
+ vector bool short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
-static vector pixel __ATTRS_o_ai
-vec_mergel(vector pixel __a, vector pixel __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector pixel __ATTRS_o_ai vec_mergel(vector pixel __a,
+ vector pixel __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
-static vector int __ATTRS_o_ai
-vec_mergel(vector int __a, vector int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+static vector int __ATTRS_o_ai vec_mergel(vector int __a, vector int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
}
-static vector unsigned int __ATTRS_o_ai
-vec_mergel(vector unsigned int __a, vector unsigned int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+static vector unsigned int __ATTRS_o_ai vec_mergel(vector unsigned int __a,
+ vector unsigned int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
}
-static vector bool int __ATTRS_o_ai
-vec_mergel(vector bool int __a, vector bool int __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+static vector bool int __ATTRS_o_ai vec_mergel(vector bool int __a,
+ vector bool int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
}
-static vector float __ATTRS_o_ai
-vec_mergel(vector float __a, vector float __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+static vector float __ATTRS_o_ai vec_mergel(vector float __a,
+ vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_mergel(vector signed long long __a, vector signed long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector signed long long __ATTRS_o_ai
+vec_mergel(vector signed long long __a, vector bool long long __b) {
+ return vec_perm(__a, (vector signed long long)__b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector signed long long __ATTRS_o_ai
+vec_mergel(vector bool long long __a, vector signed long long __b) {
+ return vec_perm((vector signed long long)__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector unsigned long long __ATTRS_o_ai
+vec_mergel(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector unsigned long long __ATTRS_o_ai
+vec_mergel(vector unsigned long long __a, vector bool long long __b) {
+ return vec_perm(__a, (vector unsigned long long)__b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector unsigned long long __ATTRS_o_ai
+vec_mergel(vector bool long long __a, vector unsigned long long __b) {
+ return vec_perm((vector unsigned long long)__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
}
+static vector double __ATTRS_o_ai
+vec_mergel(vector double __a, vector double __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector double __ATTRS_o_ai
+vec_mergel(vector double __a, vector bool long long __b) {
+ return vec_perm(__a, (vector double)__b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+static vector double __ATTRS_o_ai
+vec_mergel(vector bool long long __a, vector double __b) {
+ return vec_perm((vector double)__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+#endif
/* vec_vmrglb */
#define __builtin_altivec_vmrglb vec_vmrglb
-static vector signed char __ATTRS_o_ai
-vec_vmrglb(vector signed char __a, vector signed char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector signed char __ATTRS_o_ai vec_vmrglb(vector signed char __a,
+ vector signed char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
-static vector unsigned char __ATTRS_o_ai
-vec_vmrglb(vector unsigned char __a, vector unsigned char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector unsigned char __ATTRS_o_ai vec_vmrglb(vector unsigned char __a,
+ vector unsigned char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
-static vector bool char __ATTRS_o_ai
-vec_vmrglb(vector bool char __a, vector bool char __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+static vector bool char __ATTRS_o_ai vec_vmrglb(vector bool char __a,
+ vector bool char __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A,
+ 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D,
+ 0x0E, 0x1E, 0x0F, 0x1F));
}
/* vec_vmrglh */
#define __builtin_altivec_vmrglh vec_vmrglh
-static vector short __ATTRS_o_ai
-vec_vmrglh(vector short __a, vector short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector short __ATTRS_o_ai vec_vmrglh(vector short __a,
+ vector short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
static vector unsigned short __ATTRS_o_ai
-vec_vmrglh(vector unsigned short __a, vector unsigned short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+vec_vmrglh(vector unsigned short __a, vector unsigned short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
-static vector bool short __ATTRS_o_ai
-vec_vmrglh(vector bool short __a, vector bool short __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector bool short __ATTRS_o_ai vec_vmrglh(vector bool short __a,
+ vector bool short __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
-static vector pixel __ATTRS_o_ai
-vec_vmrglh(vector pixel __a, vector pixel __b)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+static vector pixel __ATTRS_o_ai vec_vmrglh(vector pixel __a,
+ vector pixel __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D,
+ 0x0E, 0x0F, 0x1E, 0x1F));
}
/* vec_vmrglw */
#define __builtin_altivec_vmrglw vec_vmrglw
-static vector int __ATTRS_o_ai
-vec_vmrglw(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vmrglw(vector int __a, vector int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector unsigned int __ATTRS_o_ai vec_vmrglw(vector unsigned int __a,
+ vector unsigned int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector bool int __ATTRS_o_ai vec_vmrglw(vector bool int __a,
+ vector bool int __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector float __ATTRS_o_ai vec_vmrglw(vector float __a,
+ vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
+ 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+
+#ifdef __POWER8_VECTOR__
+/* vec_mergee */
+
+static vector bool int __ATTRS_o_ai
+vec_mergee(vector bool int __a, vector bool int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
+}
+
+static vector signed int __ATTRS_o_ai
+vec_mergee(vector signed int __a, vector signed int __b) {
+ return vec_perm(__a, __b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
}
static vector unsigned int __ATTRS_o_ai
-vec_vmrglw(vector unsigned int __a, vector unsigned int __b)
-{
+vec_mergee(vector unsigned int __a, vector unsigned int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
}
-static vector bool int __ATTRS_o_ai
-vec_vmrglw(vector bool int __a, vector bool int __b)
-{
+/* vec_mergeo */
+
+static vector bool int __ATTRS_o_ai
+vec_mergeo(vector bool int __a, vector bool int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+ (0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
}
-static vector float __ATTRS_o_ai
-vec_vmrglw(vector float __a, vector float __b)
-{
+static vector signed int __ATTRS_o_ai
+vec_mergeo(vector signed int __a, vector signed int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+ (0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
}
+static vector unsigned int __ATTRS_o_ai
+vec_mergeo(vector unsigned int __a, vector unsigned int __b) {
+ return vec_perm(__a, __b, (vector unsigned char)
+ (0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+#endif
+
/* vec_mfvscr */
static vector unsigned short __attribute__((__always_inline__))
-vec_mfvscr(void)
-{
+vec_mfvscr(void) {
return __builtin_altivec_mfvscr();
}
/* vec_min */
-static vector signed char __ATTRS_o_ai
-vec_min(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_min(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vminsb(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_min(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_min(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vminsb((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_min(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_min(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vminsb(__a, (vector signed char)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_min(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_min(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vminub(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_min(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_min(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vminub((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_min(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_min(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vminub(__a, (vector unsigned char)__b);
}
-static vector short __ATTRS_o_ai
-vec_min(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_min(vector short __a, vector short __b) {
return __builtin_altivec_vminsh(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_min(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_min(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vminsh((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_min(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_min(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vminsh(__a, (vector short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_min(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_min(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vminuh(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_min(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_min(vector bool short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vminuh((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_min(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_min(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vminuh(__a, (vector unsigned short)__b);
}
-static vector int __ATTRS_o_ai
-vec_min(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_min(vector int __a, vector int __b) {
return __builtin_altivec_vminsw(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_min(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_min(vector bool int __a, vector int __b) {
return __builtin_altivec_vminsw((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_min(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_min(vector int __a, vector bool int __b) {
return __builtin_altivec_vminsw(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_min(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_min(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vminuw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_min(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_min(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vminuw((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_min(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_min(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vminuw(__a, (vector unsigned int)__b);
}
-static vector float __ATTRS_o_ai
-vec_min(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_min(vector signed long long __a, vector signed long long __b) {
+ return __builtin_altivec_vminsd(__a, __b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_min(vector bool long long __a, vector signed long long __b) {
+ return __builtin_altivec_vminsd((vector signed long long)__a, __b);
+}
+
+static vector signed long long __ATTRS_o_ai vec_min(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vminsd(__a, (vector signed long long)__b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_min(vector unsigned long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vminud(__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_min(vector bool long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vminud((vector unsigned long long)__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_min(vector unsigned long long __a, vector bool long long __b) {
+ return __builtin_altivec_vminud(__a, (vector unsigned long long)__b);
+}
+#endif
+
+static vector float __ATTRS_o_ai vec_min(vector float __a, vector float __b) {
#ifdef __VSX__
return __builtin_vsx_xvminsp(__a, __b);
#else
@@ -3338,138 +3830,115 @@ vec_min(vector float __a, vector float __b)
}
#ifdef __VSX__
-static vector double __ATTRS_o_ai
-vec_min(vector double __a, vector double __b)
-{
+static vector double __ATTRS_o_ai vec_min(vector double __a,
+ vector double __b) {
return __builtin_vsx_xvmindp(__a, __b);
}
#endif
/* vec_vminsb */
-static vector signed char __ATTRS_o_ai
-vec_vminsb(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vminsb(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vminsb(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vminsb(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vminsb(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vminsb((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vminsb(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vminsb(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vminsb(__a, (vector signed char)__b);
}
/* vec_vminub */
-static vector unsigned char __ATTRS_o_ai
-vec_vminub(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vminub(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vminub(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vminub(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vminub(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vminub((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vminub(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vminub(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vminub(__a, (vector unsigned char)__b);
}
/* vec_vminsh */
-static vector short __ATTRS_o_ai
-vec_vminsh(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vminsh(vector short __a,
+ vector short __b) {
return __builtin_altivec_vminsh(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vminsh(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vminsh(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vminsh((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vminsh(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vminsh(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vminsh(__a, (vector short)__b);
}
/* vec_vminuh */
static vector unsigned short __ATTRS_o_ai
-vec_vminuh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vminuh(vector unsigned short __a, vector unsigned short __b) {
return __builtin_altivec_vminuh(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_vminuh(vector bool short __a, vector unsigned short __b)
-{
+vec_vminuh(vector bool short __a, vector unsigned short __b) {
return __builtin_altivec_vminuh((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vminuh(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vminuh(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vminuh(__a, (vector unsigned short)__b);
}
/* vec_vminsw */
-static vector int __ATTRS_o_ai
-vec_vminsw(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vminsw(vector int __a, vector int __b) {
return __builtin_altivec_vminsw(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vminsw(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vminsw(vector bool int __a, vector int __b) {
return __builtin_altivec_vminsw((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vminsw(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vminsw(vector int __a, vector bool int __b) {
return __builtin_altivec_vminsw(__a, (vector int)__b);
}
/* vec_vminuw */
-static vector unsigned int __ATTRS_o_ai
-vec_vminuw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vminuw(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vminuw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vminuw(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vminuw(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vminuw((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vminuw(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vminuw(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vminuw(__a, (vector unsigned int)__b);
}
/* vec_vminfp */
static vector float __attribute__((__always_inline__))
-vec_vminfp(vector float __a, vector float __b)
-{
+vec_vminfp(vector float __a, vector float __b) {
#ifdef __VSX__
return __builtin_vsx_xvminsp(__a, __b);
#else
@@ -3481,250 +3950,263 @@ vec_vminfp(vector float __a, vector float __b)
#define __builtin_altivec_vmladduhm vec_mladd
-static vector short __ATTRS_o_ai
-vec_mladd(vector short __a, vector short __b, vector short __c)
-{
+static vector short __ATTRS_o_ai vec_mladd(vector short __a, vector short __b,
+ vector short __c) {
return __a * __b + __c;
}
-static vector short __ATTRS_o_ai
-vec_mladd(vector short __a, vector unsigned short __b, vector unsigned short __c)
-{
+static vector short __ATTRS_o_ai vec_mladd(vector short __a,
+ vector unsigned short __b,
+ vector unsigned short __c) {
return __a * (vector short)__b + (vector short)__c;
}
-static vector short __ATTRS_o_ai
-vec_mladd(vector unsigned short __a, vector short __b, vector short __c)
-{
+static vector short __ATTRS_o_ai vec_mladd(vector unsigned short __a,
+ vector short __b, vector short __c) {
return (vector short)__a * __b + __c;
}
-static vector unsigned short __ATTRS_o_ai
-vec_mladd(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned short __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_mladd(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned short __c) {
return __a * __b + __c;
}
/* vec_vmladduhm */
-static vector short __ATTRS_o_ai
-vec_vmladduhm(vector short __a, vector short __b, vector short __c)
-{
+static vector short __ATTRS_o_ai vec_vmladduhm(vector short __a,
+ vector short __b,
+ vector short __c) {
return __a * __b + __c;
}
-static vector short __ATTRS_o_ai
-vec_vmladduhm(vector short __a, vector unsigned short __b, vector unsigned short __c)
-{
+static vector short __ATTRS_o_ai vec_vmladduhm(vector short __a,
+ vector unsigned short __b,
+ vector unsigned short __c) {
return __a * (vector short)__b + (vector short)__c;
}
-static vector short __ATTRS_o_ai
-vec_vmladduhm(vector unsigned short __a, vector short __b, vector short __c)
-{
+static vector short __ATTRS_o_ai vec_vmladduhm(vector unsigned short __a,
+ vector short __b,
+ vector short __c) {
return (vector short)__a * __b + __c;
}
static vector unsigned short __ATTRS_o_ai
-vec_vmladduhm(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned short __c)
-{
+vec_vmladduhm(vector unsigned short __a, vector unsigned short __b,
+ vector unsigned short __c) {
return __a * __b + __c;
}
/* vec_mradds */
static vector short __attribute__((__always_inline__))
-vec_mradds(vector short __a, vector short __b, vector short __c)
-{
+vec_mradds(vector short __a, vector short __b, vector short __c) {
return __builtin_altivec_vmhraddshs(__a, __b, __c);
}
/* vec_vmhraddshs */
static vector short __attribute__((__always_inline__))
-vec_vmhraddshs(vector short __a, vector short __b, vector short __c)
-{
+vec_vmhraddshs(vector short __a, vector short __b, vector short __c) {
return __builtin_altivec_vmhraddshs(__a, __b, __c);
}
/* vec_msum */
-static vector int __ATTRS_o_ai
-vec_msum(vector signed char __a, vector unsigned char __b, vector int __c)
-{
+static vector int __ATTRS_o_ai vec_msum(vector signed char __a,
+ vector unsigned char __b,
+ vector int __c) {
return __builtin_altivec_vmsummbm(__a, __b, __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_msum(vector unsigned char __a, vector unsigned char __b, vector unsigned int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_msum(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumubm(__a, __b, __c);
}
-static vector int __ATTRS_o_ai
-vec_msum(vector short __a, vector short __b, vector int __c)
-{
+static vector int __ATTRS_o_ai vec_msum(vector short __a, vector short __b,
+ vector int __c) {
return __builtin_altivec_vmsumshm(__a, __b, __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_msum(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_msum(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumuhm(__a, __b, __c);
}
/* vec_vmsummbm */
static vector int __attribute__((__always_inline__))
-vec_vmsummbm(vector signed char __a, vector unsigned char __b, vector int __c)
-{
+vec_vmsummbm(vector signed char __a, vector unsigned char __b, vector int __c) {
return __builtin_altivec_vmsummbm(__a, __b, __c);
}
/* vec_vmsumubm */
static vector unsigned int __attribute__((__always_inline__))
-vec_vmsumubm(vector unsigned char __a,
- vector unsigned char __b,
- vector unsigned int __c)
-{
+vec_vmsumubm(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumubm(__a, __b, __c);
}
/* vec_vmsumshm */
static vector int __attribute__((__always_inline__))
-vec_vmsumshm(vector short __a, vector short __b, vector int __c)
-{
+vec_vmsumshm(vector short __a, vector short __b, vector int __c) {
return __builtin_altivec_vmsumshm(__a, __b, __c);
}
/* vec_vmsumuhm */
static vector unsigned int __attribute__((__always_inline__))
-vec_vmsumuhm(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned int __c)
-{
+vec_vmsumuhm(vector unsigned short __a, vector unsigned short __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumuhm(__a, __b, __c);
}
/* vec_msums */
-static vector int __ATTRS_o_ai
-vec_msums(vector short __a, vector short __b, vector int __c)
-{
+static vector int __ATTRS_o_ai vec_msums(vector short __a, vector short __b,
+ vector int __c) {
return __builtin_altivec_vmsumshs(__a, __b, __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_msums(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_msums(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumuhs(__a, __b, __c);
}
/* vec_vmsumshs */
static vector int __attribute__((__always_inline__))
-vec_vmsumshs(vector short __a, vector short __b, vector int __c)
-{
+vec_vmsumshs(vector short __a, vector short __b, vector int __c) {
return __builtin_altivec_vmsumshs(__a, __b, __c);
}
/* vec_vmsumuhs */
static vector unsigned int __attribute__((__always_inline__))
-vec_vmsumuhs(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned int __c)
-{
+vec_vmsumuhs(vector unsigned short __a, vector unsigned short __b,
+ vector unsigned int __c) {
return __builtin_altivec_vmsumuhs(__a, __b, __c);
}
/* vec_mtvscr */
-static void __ATTRS_o_ai
-vec_mtvscr(vector signed char __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector signed char __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector unsigned char __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector unsigned char __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector bool char __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector bool char __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector short __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector short __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector unsigned short __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector unsigned short __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector bool short __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector bool short __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector pixel __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector pixel __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector int __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector int __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector unsigned int __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector unsigned int __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector bool int __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector bool int __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
-static void __ATTRS_o_ai
-vec_mtvscr(vector float __a)
-{
+static void __ATTRS_o_ai vec_mtvscr(vector float __a) {
__builtin_altivec_mtvscr((vector int)__a);
}
+/* vec_mul */
+
+/* Integer vector multiplication will involve multiplication of the odd/even
+ elements separately, then truncating the results and moving to the
+ result vector.
+*/
+static vector signed char __ATTRS_o_ai vec_mul(vector signed char __a,
+ vector signed char __b) {
+ return __a * __b;
+}
+
+static vector unsigned char __ATTRS_o_ai vec_mul(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __a * __b;
+}
+
+static vector signed short __ATTRS_o_ai vec_mul(vector signed short __a,
+ vector signed short __b) {
+ return __a * __b;
+}
+
+static vector unsigned short __ATTRS_o_ai vec_mul(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __a * __b;
+}
+
+static vector signed int __ATTRS_o_ai vec_mul(vector signed int __a,
+ vector signed int __b) {
+ return __a * __b;
+}
+
+static vector unsigned int __ATTRS_o_ai vec_mul(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __a * __b;
+}
+
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_mul(vector signed long long __a, vector signed long long __b) {
+ return __a * __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_mul(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a * __b;
+}
+#endif
+
+static vector float __ATTRS_o_ai vec_mul(vector float __a, vector float __b) {
+ return __a * __b;
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_mul(vector double __a, vector double __b) {
+ return __a * __b;
+}
+#endif
+
/* The vmulos* and vmules* instructions have a big endian bias, so
we must reverse the meaning of "even" and "odd" for little endian. */
/* vec_mule */
-static vector short __ATTRS_o_ai
-vec_mule(vector signed char __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_mule(vector signed char __a,
+ vector signed char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulosb(__a, __b);
#else
@@ -3732,9 +4214,8 @@ vec_mule(vector signed char __a, vector signed char __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_mule(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_mule(vector unsigned char __a,
+ vector unsigned char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuloub(__a, __b);
#else
@@ -3742,9 +4223,7 @@ vec_mule(vector unsigned char __a, vector unsigned char __b)
#endif
}
-static vector int __ATTRS_o_ai
-vec_mule(vector short __a, vector short __b)
-{
+static vector int __ATTRS_o_ai vec_mule(vector short __a, vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulosh(__a, __b);
#else
@@ -3752,9 +4231,8 @@ vec_mule(vector short __a, vector short __b)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_mule(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_mule(vector unsigned short __a,
+ vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulouh(__a, __b);
#else
@@ -3762,11 +4240,30 @@ vec_mule(vector unsigned short __a, vector unsigned short __b)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai vec_mule(vector signed int __a,
+ vector signed int __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulosw(__a, __b);
+#else
+ return __builtin_altivec_vmulesw(__a, __b);
+#endif
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_mule(vector unsigned int __a, vector unsigned int __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulouw(__a, __b);
+#else
+ return __builtin_altivec_vmuleuw(__a, __b);
+#endif
+}
+#endif
+
/* vec_vmulesb */
static vector short __attribute__((__always_inline__))
-vec_vmulesb(vector signed char __a, vector signed char __b)
-{
+vec_vmulesb(vector signed char __a, vector signed char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulosb(__a, __b);
#else
@@ -3777,8 +4274,7 @@ vec_vmulesb(vector signed char __a, vector signed char __b)
/* vec_vmuleub */
static vector unsigned short __attribute__((__always_inline__))
-vec_vmuleub(vector unsigned char __a, vector unsigned char __b)
-{
+vec_vmuleub(vector unsigned char __a, vector unsigned char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuloub(__a, __b);
#else
@@ -3789,8 +4285,7 @@ vec_vmuleub(vector unsigned char __a, vector unsigned char __b)
/* vec_vmulesh */
static vector int __attribute__((__always_inline__))
-vec_vmulesh(vector short __a, vector short __b)
-{
+vec_vmulesh(vector short __a, vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulosh(__a, __b);
#else
@@ -3801,8 +4296,7 @@ vec_vmulesh(vector short __a, vector short __b)
/* vec_vmuleuh */
static vector unsigned int __attribute__((__always_inline__))
-vec_vmuleuh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vmuleuh(vector unsigned short __a, vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulouh(__a, __b);
#else
@@ -3812,9 +4306,8 @@ vec_vmuleuh(vector unsigned short __a, vector unsigned short __b)
/* vec_mulo */
-static vector short __ATTRS_o_ai
-vec_mulo(vector signed char __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_mulo(vector signed char __a,
+ vector signed char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulesb(__a, __b);
#else
@@ -3822,9 +4315,8 @@ vec_mulo(vector signed char __a, vector signed char __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_mulo(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_mulo(vector unsigned char __a,
+ vector unsigned char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuleub(__a, __b);
#else
@@ -3832,9 +4324,7 @@ vec_mulo(vector unsigned char __a, vector unsigned char __b)
#endif
}
-static vector int __ATTRS_o_ai
-vec_mulo(vector short __a, vector short __b)
-{
+static vector int __ATTRS_o_ai vec_mulo(vector short __a, vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulesh(__a, __b);
#else
@@ -3842,9 +4332,8 @@ vec_mulo(vector short __a, vector short __b)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_mulo(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_mulo(vector unsigned short __a,
+ vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuleuh(__a, __b);
#else
@@ -3852,11 +4341,30 @@ vec_mulo(vector unsigned short __a, vector unsigned short __b)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai vec_mulo(vector signed int __a,
+ vector signed int __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulesw(__a, __b);
+#else
+ return __builtin_altivec_vmulosw(__a, __b);
+#endif
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_mulo(vector unsigned int __a, vector unsigned int __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuleuw(__a, __b);
+#else
+ return __builtin_altivec_vmulouw(__a, __b);
+#endif
+}
+#endif
+
/* vec_vmulosb */
static vector short __attribute__((__always_inline__))
-vec_vmulosb(vector signed char __a, vector signed char __b)
-{
+vec_vmulosb(vector signed char __a, vector signed char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulesb(__a, __b);
#else
@@ -3867,8 +4375,7 @@ vec_vmulosb(vector signed char __a, vector signed char __b)
/* vec_vmuloub */
static vector unsigned short __attribute__((__always_inline__))
-vec_vmuloub(vector unsigned char __a, vector unsigned char __b)
-{
+vec_vmuloub(vector unsigned char __a, vector unsigned char __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuleub(__a, __b);
#else
@@ -3879,8 +4386,7 @@ vec_vmuloub(vector unsigned char __a, vector unsigned char __b)
/* vec_vmulosh */
static vector int __attribute__((__always_inline__))
-vec_vmulosh(vector short __a, vector short __b)
-{
+vec_vmulosh(vector short __a, vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmulesh(__a, __b);
#else
@@ -3891,8 +4397,7 @@ vec_vmulosh(vector short __a, vector short __b)
/* vec_vmulouh */
static vector unsigned int __attribute__((__always_inline__))
-vec_vmulouh(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vmulouh(vector unsigned short __a, vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vmuleuh(__a, __b);
#else
@@ -3900,19 +4405,170 @@ vec_vmulouh(vector unsigned short __a, vector unsigned short __b)
#endif
}
+/* vec_nand */
+
+#ifdef __POWER8_VECTOR__
+static vector signed char __ATTRS_o_ai vec_nand(vector signed char __a,
+ vector signed char __b) {
+ return ~(__a & __b);
+}
+
+static vector signed char __ATTRS_o_ai vec_nand(vector signed char __a,
+ vector bool char __b) {
+ return ~(__a & __b);
+}
+
+static vector signed char __ATTRS_o_ai vec_nand(vector bool char __a,
+ vector signed char __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_nand(vector unsigned char __a,
+ vector unsigned char __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_nand(vector unsigned char __a,
+ vector bool char __b) {
+ return ~(__a & __b);
+
+}
+
+static vector unsigned char __ATTRS_o_ai vec_nand(vector bool char __a,
+ vector unsigned char __b) {
+ return ~(__a & __b);
+}
+
+static vector signed short __ATTRS_o_ai vec_nand(vector signed short __a,
+ vector signed short __b) {
+ return ~(__a & __b);
+}
+
+static vector signed short __ATTRS_o_ai vec_nand(vector signed short __a,
+ vector bool short __b) {
+ return ~(__a & __b);
+}
+
+static vector signed short __ATTRS_o_ai vec_nand(vector bool short __a,
+ vector signed short __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned short __ATTRS_o_ai vec_nand(vector unsigned short __a,
+ vector unsigned short __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned short __ATTRS_o_ai vec_nand(vector unsigned short __a,
+ vector bool short __b) {
+ return ~(__a & __b);
+
+}
+
+static vector unsigned short __ATTRS_o_ai vec_nand(vector bool short __a,
+ vector unsigned short __b) {
+ return ~(__a & __b);
+
+}
+
+static vector signed int __ATTRS_o_ai vec_nand(vector signed int __a,
+ vector signed int __b) {
+ return ~(__a & __b);
+}
+
+static vector signed int __ATTRS_o_ai vec_nand(vector signed int __a,
+ vector bool int __b) {
+ return ~(__a & __b);
+}
+
+static vector signed int __ATTRS_o_ai vec_nand(vector bool int __a,
+ vector signed int __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_nand(vector unsigned int __a,
+ vector unsigned int __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_nand(vector unsigned int __a,
+ vector bool int __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned int __ATTRS_o_ai vec_nand(vector bool int __a,
+ vector unsigned int __b) {
+ return ~(__a & __b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_nand(vector signed long long __a, vector signed long long __b) {
+ return ~(__a & __b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_nand(vector signed long long __a, vector bool long long __b) {
+ return ~(__a & __b);
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_nand(vector bool long long __a, vector signed long long __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_nand(vector unsigned long long __a, vector unsigned long long __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_nand(vector unsigned long long __a, vector bool long long __b) {
+ return ~(__a & __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_nand(vector bool long long __a, vector unsigned long long __b) {
+ return ~(__a & __b);
+}
+
+#endif
+
+/* vec_nmadd */
+
+#ifdef __VSX__
+static vector float __ATTRS_o_ai
+vec_nmadd(vector float __a, vector float __b, vector float __c) {
+ return __builtin_vsx_xvnmaddasp(__a, __b, __c);
+}
+
+static vector double __ATTRS_o_ai
+vec_nmadd(vector double __a, vector double __b, vector double __c) {
+ return __builtin_vsx_xvnmaddadp(__a, __b, __c);
+}
+#endif
+
/* vec_nmsub */
-static vector float __attribute__((__always_inline__))
-vec_nmsub(vector float __a, vector float __b, vector float __c)
-{
+static vector float __ATTRS_o_ai
+vec_nmsub(vector float __a, vector float __b, vector float __c) {
+#ifdef __VSX__
+ return __builtin_vsx_xvnmsubasp(__a, __b, __c);
+#else
return __builtin_altivec_vnmsubfp(__a, __b, __c);
+#endif
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_nmsub(vector double __a, vector double __b, vector double __c) {
+ return __builtin_vsx_xvnmsubadp(__a, __b, __c);
}
+#endif
/* vec_vnmsubfp */
static vector float __attribute__((__always_inline__))
-vec_vnmsubfp(vector float __a, vector float __b, vector float __c)
-{
+vec_vnmsubfp(vector float __a, vector float __b, vector float __c) {
return __builtin_altivec_vnmsubfp(__a, __b, __c);
}
@@ -3920,562 +4576,777 @@ vec_vnmsubfp(vector float __a, vector float __b, vector float __c)
#define __builtin_altivec_vnor vec_nor
-static vector signed char __ATTRS_o_ai
-vec_nor(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_nor(vector signed char __a,
+ vector signed char __b) {
return ~(__a | __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_nor(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_nor(vector unsigned char __a,
+ vector unsigned char __b) {
return ~(__a | __b);
}
-static vector bool char __ATTRS_o_ai
-vec_nor(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_nor(vector bool char __a,
+ vector bool char __b) {
return ~(__a | __b);
}
-static vector short __ATTRS_o_ai
-vec_nor(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_nor(vector short __a, vector short __b) {
return ~(__a | __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_nor(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_nor(vector unsigned short __a,
+ vector unsigned short __b) {
return ~(__a | __b);
}
-static vector bool short __ATTRS_o_ai
-vec_nor(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_nor(vector bool short __a,
+ vector bool short __b) {
return ~(__a | __b);
}
-static vector int __ATTRS_o_ai
-vec_nor(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_nor(vector int __a, vector int __b) {
return ~(__a | __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_nor(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_nor(vector unsigned int __a,
+ vector unsigned int __b) {
return ~(__a | __b);
}
-static vector bool int __ATTRS_o_ai
-vec_nor(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_nor(vector bool int __a,
+ vector bool int __b) {
return ~(__a | __b);
}
-static vector float __ATTRS_o_ai
-vec_nor(vector float __a, vector float __b)
-{
- vector unsigned int __res = ~((vector unsigned int)__a | (vector unsigned int)__b);
+static vector float __ATTRS_o_ai vec_nor(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ ~((vector unsigned int)__a | (vector unsigned int)__b);
return (vector float)__res;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_nor(vector double __a, vector double __b) {
+ vector unsigned long long __res =
+ ~((vector unsigned long long)__a | (vector unsigned long long)__b);
+ return (vector double)__res;
+}
+#endif
+
/* vec_vnor */
-static vector signed char __ATTRS_o_ai
-vec_vnor(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vnor(vector signed char __a,
+ vector signed char __b) {
return ~(__a | __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vnor(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vnor(vector unsigned char __a,
+ vector unsigned char __b) {
return ~(__a | __b);
}
-static vector bool char __ATTRS_o_ai
-vec_vnor(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vnor(vector bool char __a,
+ vector bool char __b) {
return ~(__a | __b);
}
-static vector short __ATTRS_o_ai
-vec_vnor(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vnor(vector short __a, vector short __b) {
return ~(__a | __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vnor(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vnor(vector unsigned short __a,
+ vector unsigned short __b) {
return ~(__a | __b);
}
-static vector bool short __ATTRS_o_ai
-vec_vnor(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_vnor(vector bool short __a,
+ vector bool short __b) {
return ~(__a | __b);
}
-static vector int __ATTRS_o_ai
-vec_vnor(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vnor(vector int __a, vector int __b) {
return ~(__a | __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vnor(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vnor(vector unsigned int __a,
+ vector unsigned int __b) {
return ~(__a | __b);
}
-static vector bool int __ATTRS_o_ai
-vec_vnor(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_vnor(vector bool int __a,
+ vector bool int __b) {
return ~(__a | __b);
}
-static vector float __ATTRS_o_ai
-vec_vnor(vector float __a, vector float __b)
-{
- vector unsigned int __res = ~((vector unsigned int)__a | (vector unsigned int)__b);
+static vector float __ATTRS_o_ai vec_vnor(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ ~((vector unsigned int)__a | (vector unsigned int)__b);
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_nor(vector signed long long __a, vector signed long long __b) {
+ return ~(__a | __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_nor(vector unsigned long long __a, vector unsigned long long __b) {
+ return ~(__a | __b);
+}
+
+static vector bool long long __ATTRS_o_ai vec_nor(vector bool long long __a,
+ vector bool long long __b) {
+ return ~(__a | __b);
+}
+#endif
+
/* vec_or */
#define __builtin_altivec_vor vec_or
-static vector signed char __ATTRS_o_ai
-vec_or(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_or(vector signed char __a,
+ vector signed char __b) {
return __a | __b;
}
-static vector signed char __ATTRS_o_ai
-vec_or(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_or(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a | __b;
}
-static vector signed char __ATTRS_o_ai
-vec_or(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_or(vector signed char __a,
+ vector bool char __b) {
return __a | (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_or(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_or(vector unsigned char __a,
+ vector unsigned char __b) {
return __a | __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_or(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_or(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a | __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_or(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_or(vector unsigned char __a,
+ vector bool char __b) {
return __a | (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_or(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_or(vector bool char __a,
+ vector bool char __b) {
return __a | __b;
}
-static vector short __ATTRS_o_ai
-vec_or(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_or(vector short __a, vector short __b) {
return __a | __b;
}
-static vector short __ATTRS_o_ai
-vec_or(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_or(vector bool short __a,
+ vector short __b) {
return (vector short)__a | __b;
}
-static vector short __ATTRS_o_ai
-vec_or(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_or(vector short __a,
+ vector bool short __b) {
return __a | (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_or(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_or(vector unsigned short __a,
+ vector unsigned short __b) {
return __a | __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_or(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_or(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a | __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_or(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_or(vector unsigned short __a,
+ vector bool short __b) {
return __a | (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_or(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_or(vector bool short __a,
+ vector bool short __b) {
return __a | __b;
}
-static vector int __ATTRS_o_ai
-vec_or(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_or(vector int __a, vector int __b) {
return __a | __b;
}
-static vector int __ATTRS_o_ai
-vec_or(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_or(vector bool int __a, vector int __b) {
return (vector int)__a | __b;
}
-static vector int __ATTRS_o_ai
-vec_or(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_or(vector int __a, vector bool int __b) {
return __a | (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_or(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_or(vector unsigned int __a,
+ vector unsigned int __b) {
return __a | __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_or(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_or(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a | __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_or(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_or(vector unsigned int __a,
+ vector bool int __b) {
return __a | (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_or(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_or(vector bool int __a,
+ vector bool int __b) {
return __a | __b;
}
-static vector float __ATTRS_o_ai
-vec_or(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_or(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_or(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_or(vector bool int __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_or(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_or(vector float __a, vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_or(vector bool long long __a,
+ vector double __b) {
+ return (vector unsigned long long)__a | (vector unsigned long long)__b;
+}
+
+static vector double __ATTRS_o_ai vec_or(vector double __a,
+ vector bool long long __b) {
+ return (vector unsigned long long)__a | (vector unsigned long long)__b;
+}
+
+static vector double __ATTRS_o_ai vec_or(vector double __a, vector double __b) {
+ vector unsigned long long __res =
+ (vector unsigned long long)__a | (vector unsigned long long)__b;
+ return (vector double)__res;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_or(vector signed long long __a, vector signed long long __b) {
+ return __a | __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_or(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a | __b;
+}
+
+static vector signed long long __ATTRS_o_ai vec_or(vector signed long long __a,
+ vector bool long long __b) {
+ return __a | (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_or(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a | __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_or(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a | __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_or(vector unsigned long long __a, vector bool long long __b) {
+ return __a | (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_or(vector bool long long __a,
+ vector bool long long __b) {
+ return __a | __b;
+}
+#endif
+
+#ifdef __POWER8_VECTOR__
+static vector signed char __ATTRS_o_ai vec_orc(vector signed char __a,
+ vector signed char __b) {
+ return __a | ~__b;
+}
+
+static vector signed char __ATTRS_o_ai vec_orc(vector signed char __a,
+ vector bool char __b) {
+ return __a | ~__b;
+}
+
+static vector signed char __ATTRS_o_ai vec_orc(vector bool char __a,
+ vector signed char __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned char __ATTRS_o_ai vec_orc(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned char __ATTRS_o_ai vec_orc(vector unsigned char __a,
+ vector bool char __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned char __ATTRS_o_ai vec_orc(vector bool char __a,
+ vector unsigned char __b) {
+ return __a | ~__b;
+}
+
+static vector signed short __ATTRS_o_ai vec_orc(vector signed short __a,
+ vector signed short __b) {
+ return __a | ~__b;
+}
+
+static vector signed short __ATTRS_o_ai vec_orc(vector signed short __a,
+ vector bool short __b) {
+ return __a | ~__b;
+}
+
+static vector signed short __ATTRS_o_ai vec_orc(vector bool short __a,
+ vector signed short __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned short __ATTRS_o_ai vec_orc(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned short __ATTRS_o_ai vec_orc(vector unsigned short __a,
+ vector bool short __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_orc(vector bool short __a, vector unsigned short __b) {
+ return __a | ~__b;
+}
+
+static vector signed int __ATTRS_o_ai vec_orc(vector signed int __a,
+ vector signed int __b) {
+ return __a | ~__b;
+}
+
+static vector signed int __ATTRS_o_ai vec_orc(vector signed int __a,
+ vector bool int __b) {
+ return __a | ~__b;
+}
+
+static vector signed int __ATTRS_o_ai vec_orc(vector bool int __a,
+ vector signed int __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned int __ATTRS_o_ai vec_orc(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned int __ATTRS_o_ai vec_orc(vector unsigned int __a,
+ vector bool int __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned int __ATTRS_o_ai vec_orc(vector bool int __a,
+ vector unsigned int __b) {
+ return __a | ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_orc(vector signed long long __a, vector signed long long __b) {
+ return __a | ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai vec_orc(vector signed long long __a,
+ vector bool long long __b) {
+ return __a | ~__b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_orc(vector bool long long __a, vector signed long long __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_orc(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_orc(vector unsigned long long __a, vector bool long long __b) {
+ return __a | ~__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_orc(vector bool long long __a, vector unsigned long long __b) {
+ return __a | ~__b;
+}
+#endif
+
/* vec_vor */
-static vector signed char __ATTRS_o_ai
-vec_vor(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vor(vector signed char __a,
+ vector signed char __b) {
return __a | __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vor(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vor(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a | __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vor(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vor(vector signed char __a,
+ vector bool char __b) {
return __a | (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vor(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vor(vector unsigned char __a,
+ vector unsigned char __b) {
return __a | __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vor(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vor(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a | __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vor(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vor(vector unsigned char __a,
+ vector bool char __b) {
return __a | (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_vor(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vor(vector bool char __a,
+ vector bool char __b) {
return __a | __b;
}
-static vector short __ATTRS_o_ai
-vec_vor(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vor(vector short __a, vector short __b) {
return __a | __b;
}
-static vector short __ATTRS_o_ai
-vec_vor(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vor(vector bool short __a,
+ vector short __b) {
return (vector short)__a | __b;
}
-static vector short __ATTRS_o_ai
-vec_vor(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vor(vector short __a,
+ vector bool short __b) {
return __a | (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vor(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vor(vector unsigned short __a,
+ vector unsigned short __b) {
return __a | __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vor(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vor(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a | __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vor(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vor(vector unsigned short __a,
+ vector bool short __b) {
return __a | (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_vor(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_vor(vector bool short __a,
+ vector bool short __b) {
return __a | __b;
}
-static vector int __ATTRS_o_ai
-vec_vor(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vor(vector int __a, vector int __b) {
return __a | __b;
}
-static vector int __ATTRS_o_ai
-vec_vor(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vor(vector bool int __a, vector int __b) {
return (vector int)__a | __b;
}
-static vector int __ATTRS_o_ai
-vec_vor(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vor(vector int __a, vector bool int __b) {
return __a | (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vor(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vor(vector unsigned int __a,
+ vector unsigned int __b) {
return __a | __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vor(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vor(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a | __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vor(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vor(vector unsigned int __a,
+ vector bool int __b) {
return __a | (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_vor(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_vor(vector bool int __a,
+ vector bool int __b) {
return __a | __b;
}
-static vector float __ATTRS_o_ai
-vec_vor(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vor(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vor(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vor(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vor(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vor(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a | (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_vor(vector signed long long __a, vector signed long long __b) {
+ return __a | __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vor(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a | __b;
+}
+
+static vector signed long long __ATTRS_o_ai vec_vor(vector signed long long __a,
+ vector bool long long __b) {
+ return __a | (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vor(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a | __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vor(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a | __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vor(vector unsigned long long __a, vector bool long long __b) {
+ return __a | (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_vor(vector bool long long __a,
+ vector bool long long __b) {
+ return __a | __b;
+}
+#endif
+
/* vec_pack */
/* The various vector pack instructions have a big-endian bias, so for
little endian we must handle reversed element numbering. */
-static vector signed char __ATTRS_o_ai
-vec_pack(vector signed short __a, vector signed short __b)
-{
+static vector signed char __ATTRS_o_ai vec_pack(vector signed short __a,
+ vector signed short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector signed char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector signed char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector signed char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector signed char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
-static vector unsigned char __ATTRS_o_ai
-vec_pack(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_pack(vector unsigned short __a,
+ vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector unsigned char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector unsigned char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector unsigned char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector unsigned char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
-static vector bool char __ATTRS_o_ai
-vec_pack(vector bool short __a, vector bool short __b)
-{
+static vector bool char __ATTRS_o_ai vec_pack(vector bool short __a,
+ vector bool short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector bool char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector bool char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector bool char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector bool char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
-static vector short __ATTRS_o_ai
-vec_pack(vector int __a, vector int __b)
-{
+static vector short __ATTRS_o_ai vec_pack(vector int __a, vector int __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
#else
- return (vector short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_pack(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_pack(vector unsigned int __a,
+ vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector unsigned short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector unsigned short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
#else
- return (vector unsigned short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector unsigned short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_pack(vector bool int __a, vector bool int __b)
-{
+static vector bool short __ATTRS_o_ai vec_pack(vector bool int __a,
+ vector bool int __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector bool short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector bool short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
#else
- return (vector bool short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector bool short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
#endif
}
+#ifdef __VSX__
+static vector signed int __ATTRS_o_ai vec_pack(vector signed long long __a,
+ vector signed long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector signed int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
+#else
+ return (vector signed int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
+#endif
+}
+static vector unsigned int __ATTRS_o_ai
+vec_pack(vector unsigned long long __a, vector unsigned long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector unsigned int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
+#else
+ return (vector unsigned int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
+#endif
+}
+
+static vector bool int __ATTRS_o_ai vec_pack(vector bool long long __a,
+ vector bool long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
+#else
+ return (vector bool int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
+#endif
+}
+
+#endif
+
/* vec_vpkuhum */
#define __builtin_altivec_vpkuhum vec_vpkuhum
-static vector signed char __ATTRS_o_ai
-vec_vpkuhum(vector signed short __a, vector signed short __b)
-{
+static vector signed char __ATTRS_o_ai vec_vpkuhum(vector signed short __a,
+ vector signed short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector signed char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector signed char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector signed char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector signed char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
static vector unsigned char __ATTRS_o_ai
-vec_vpkuhum(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vpkuhum(vector unsigned short __a, vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector unsigned char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector unsigned char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector unsigned char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector unsigned char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
-static vector bool char __ATTRS_o_ai
-vec_vpkuhum(vector bool short __a, vector bool short __b)
-{
+static vector bool char __ATTRS_o_ai vec_vpkuhum(vector bool short __a,
+ vector bool short __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector bool char)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
+ return (vector bool char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E));
#else
- return (vector bool char)vec_perm(__a, __b, (vector unsigned char)
- (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+ return (vector bool char)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
#endif
}
@@ -4483,53 +5354,105 @@ vec_vpkuhum(vector bool short __a, vector bool short __b)
#define __builtin_altivec_vpkuwum vec_vpkuwum
-static vector short __ATTRS_o_ai
-vec_vpkuwum(vector int __a, vector int __b)
-{
+static vector short __ATTRS_o_ai vec_vpkuwum(vector int __a, vector int __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
#else
- return (vector short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_vpkuwum(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vpkuwum(vector unsigned int __a,
+ vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector unsigned short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector unsigned short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
#else
- return (vector unsigned short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector unsigned short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_vpkuwum(vector bool int __a, vector bool int __b)
-{
+static vector bool short __ATTRS_o_ai vec_vpkuwum(vector bool int __a,
+ vector bool int __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
+ 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+#else
+ return (vector bool short)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+#endif
+}
+
+/* vec_vpkudum */
+
+#ifdef __POWER8_VECTOR__
+#define __builtin_altivec_vpkudum vec_vpkudum
+
+static vector int __ATTRS_o_ai vec_vpkudum(vector long long __a,
+ vector long long __b) {
#ifdef __LITTLE_ENDIAN__
- return (vector bool short)vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D));
+ return (vector int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
#else
- return (vector bool short)vec_perm(__a, __b, (vector unsigned char)
- (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+ return (vector int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
#endif
}
+static vector unsigned int __ATTRS_o_ai
+vec_vpkudum(vector unsigned long long __a, vector unsigned long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector unsigned int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
+#else
+ return (vector unsigned int)vec_perm(
+ __a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
+#endif
+}
+
+static vector bool int __ATTRS_o_ai vec_vpkudum(vector bool long long __a,
+ vector bool long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool int)vec_perm(
+ (vector long long)__a, (vector long long)__b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B));
+#else
+ return (vector bool int)vec_perm(
+ (vector long long)__a, (vector long long)__b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F));
+#endif
+}
+#endif
+
/* vec_packpx */
static vector pixel __attribute__((__always_inline__))
-vec_packpx(vector unsigned int __a, vector unsigned int __b)
-{
+vec_packpx(vector unsigned int __a, vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return (vector pixel)__builtin_altivec_vpkpx(__b, __a);
#else
@@ -4540,8 +5463,7 @@ vec_packpx(vector unsigned int __a, vector unsigned int __b)
/* vec_vpkpx */
static vector pixel __attribute__((__always_inline__))
-vec_vpkpx(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vpkpx(vector unsigned int __a, vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return (vector pixel)__builtin_altivec_vpkpx(__b, __a);
#else
@@ -4551,9 +5473,8 @@ vec_vpkpx(vector unsigned int __a, vector unsigned int __b)
/* vec_packs */
-static vector signed char __ATTRS_o_ai
-vec_packs(vector short __a, vector short __b)
-{
+static vector signed char __ATTRS_o_ai vec_packs(vector short __a,
+ vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkshss(__b, __a);
#else
@@ -4561,9 +5482,8 @@ vec_packs(vector short __a, vector short __b)
#endif
}
-static vector unsigned char __ATTRS_o_ai
-vec_packs(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_packs(vector unsigned short __a,
+ vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuhus(__b, __a);
#else
@@ -4571,9 +5491,8 @@ vec_packs(vector unsigned short __a, vector unsigned short __b)
#endif
}
-static vector signed short __ATTRS_o_ai
-vec_packs(vector int __a, vector int __b)
-{
+static vector signed short __ATTRS_o_ai vec_packs(vector int __a,
+ vector int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkswss(__b, __a);
#else
@@ -4581,9 +5500,8 @@ vec_packs(vector int __a, vector int __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_packs(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_packs(vector unsigned int __a,
+ vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuwus(__b, __a);
#else
@@ -4591,11 +5509,30 @@ vec_packs(vector unsigned int __a, vector unsigned int __b)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector int __ATTRS_o_ai vec_packs(vector long long __a,
+ vector long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpksdss(__b, __a);
+#else
+ return __builtin_altivec_vpksdss(__a, __b);
+#endif
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_packs(vector unsigned long long __a, vector unsigned long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpkudus(__b, __a);
+#else
+ return __builtin_altivec_vpkudus(__a, __b);
+#endif
+}
+#endif
+
/* vec_vpkshss */
static vector signed char __attribute__((__always_inline__))
-vec_vpkshss(vector short __a, vector short __b)
-{
+vec_vpkshss(vector short __a, vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkshss(__b, __a);
#else
@@ -4603,11 +5540,23 @@ vec_vpkshss(vector short __a, vector short __b)
#endif
}
+/* vec_vpksdss */
+
+#ifdef __POWER8_VECTOR__
+static vector int __ATTRS_o_ai vec_vpksdss(vector long long __a,
+ vector long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpksdss(__b, __a);
+#else
+ return __builtin_altivec_vpksdss(__a, __b);
+#endif
+}
+#endif
+
/* vec_vpkuhus */
static vector unsigned char __attribute__((__always_inline__))
-vec_vpkuhus(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vpkuhus(vector unsigned short __a, vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuhus(__b, __a);
#else
@@ -4615,11 +5564,23 @@ vec_vpkuhus(vector unsigned short __a, vector unsigned short __b)
#endif
}
+/* vec_vpkudus */
+
+#ifdef __POWER8_VECTOR__
+static vector unsigned int __attribute__((__always_inline__))
+vec_vpkudus(vector unsigned long long __a, vector unsigned long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpkudus(__b, __a);
+#else
+ return __builtin_altivec_vpkudus(__a, __b);
+#endif
+}
+#endif
+
/* vec_vpkswss */
static vector signed short __attribute__((__always_inline__))
-vec_vpkswss(vector int __a, vector int __b)
-{
+vec_vpkswss(vector int __a, vector int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkswss(__b, __a);
#else
@@ -4630,8 +5591,7 @@ vec_vpkswss(vector int __a, vector int __b)
/* vec_vpkuwus */
static vector unsigned short __attribute__((__always_inline__))
-vec_vpkuwus(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vpkuwus(vector unsigned int __a, vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuwus(__b, __a);
#else
@@ -4641,9 +5601,8 @@ vec_vpkuwus(vector unsigned int __a, vector unsigned int __b)
/* vec_packsu */
-static vector unsigned char __ATTRS_o_ai
-vec_packsu(vector short __a, vector short __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_packsu(vector short __a,
+ vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkshus(__b, __a);
#else
@@ -4651,9 +5610,8 @@ vec_packsu(vector short __a, vector short __b)
#endif
}
-static vector unsigned char __ATTRS_o_ai
-vec_packsu(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_packsu(vector unsigned short __a,
+ vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuhus(__b, __a);
#else
@@ -4661,9 +5619,8 @@ vec_packsu(vector unsigned short __a, vector unsigned short __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_packsu(vector int __a, vector int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_packsu(vector int __a,
+ vector int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkswus(__b, __a);
#else
@@ -4671,9 +5628,8 @@ vec_packsu(vector int __a, vector int __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_packsu(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_packsu(vector unsigned int __a,
+ vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuwus(__b, __a);
#else
@@ -4681,11 +5637,30 @@ vec_packsu(vector unsigned int __a, vector unsigned int __b)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector unsigned int __ATTRS_o_ai vec_packsu(vector long long __a,
+ vector long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpksdus(__b, __a);
+#else
+ return __builtin_altivec_vpksdus(__a, __b);
+#endif
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_packsu(vector unsigned long long __a, vector unsigned long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpkudus(__b, __a);
+#else
+ return __builtin_altivec_vpkudus(__a, __b);
+#endif
+}
+#endif
+
/* vec_vpkshus */
-static vector unsigned char __ATTRS_o_ai
-vec_vpkshus(vector short __a, vector short __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vpkshus(vector short __a,
+ vector short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkshus(__b, __a);
#else
@@ -4694,8 +5669,7 @@ vec_vpkshus(vector short __a, vector short __b)
}
static vector unsigned char __ATTRS_o_ai
-vec_vpkshus(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vpkshus(vector unsigned short __a, vector unsigned short __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuhus(__b, __a);
#else
@@ -4705,9 +5679,8 @@ vec_vpkshus(vector unsigned short __a, vector unsigned short __b)
/* vec_vpkswus */
-static vector unsigned short __ATTRS_o_ai
-vec_vpkswus(vector int __a, vector int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vpkswus(vector int __a,
+ vector int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkswus(__b, __a);
#else
@@ -4715,9 +5688,8 @@ vec_vpkswus(vector int __a, vector int __b)
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_vpkswus(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vpkswus(vector unsigned int __a,
+ vector unsigned int __b) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vpkuwus(__b, __a);
#else
@@ -4725,6 +5697,19 @@ vec_vpkswus(vector unsigned int __a, vector unsigned int __b)
#endif
}
+/* vec_vpksdus */
+
+#ifdef __POWER8_VECTOR__
+static vector unsigned int __ATTRS_o_ai vec_vpksdus(vector long long __a,
+ vector long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vpksdus(__b, __a);
+#else
+ return __builtin_altivec_vpksdus(__a, __b);
+#endif
+}
+#endif
+
/* vec_perm */
// The vperm instruction is defined architecturally with a big-endian bias.
@@ -4735,437 +5720,493 @@ vec_vpkswus(vector unsigned int __a, vector unsigned int __b)
// in that the vec_xor can be recognized as a vec_nor (and for P8 and
// later, possibly a vec_nand).
-static vector signed char __ATTRS_o_ai
-vec_perm(vector signed char __a, vector signed char __b, vector unsigned char __c)
-{
+static vector signed char __ATTRS_o_ai vec_perm(vector signed char __a,
+ vector signed char __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector signed char)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector signed char)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector signed char)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector signed char)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector unsigned char __ATTRS_o_ai
-vec_perm(vector unsigned char __a,
- vector unsigned char __b,
- vector unsigned char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_perm(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector unsigned char)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector unsigned char)__builtin_altivec_vperm_4si(
+ (vector int)__b, (vector int)__a, __d);
#else
- return (vector unsigned char)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector unsigned char)__builtin_altivec_vperm_4si(
+ (vector int)__a, (vector int)__b, __c);
#endif
}
-static vector bool char __ATTRS_o_ai
-vec_perm(vector bool char __a, vector bool char __b, vector unsigned char __c)
-{
+static vector bool char __ATTRS_o_ai vec_perm(vector bool char __a,
+ vector bool char __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector bool char)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector bool char)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector bool char)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector bool char)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector short __ATTRS_o_ai
-vec_perm(vector short __a, vector short __b, vector unsigned char __c)
-{
+static vector short __ATTRS_o_ai vec_perm(vector signed short __a,
+ vector signed short __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector short)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector signed short)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector short)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector signed short)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector unsigned short __ATTRS_o_ai
-vec_perm(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned char __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_perm(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector unsigned short)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector unsigned short)__builtin_altivec_vperm_4si(
+ (vector int)__b, (vector int)__a, __d);
#else
- return (vector unsigned short)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector unsigned short)__builtin_altivec_vperm_4si(
+ (vector int)__a, (vector int)__b, __c);
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_perm(vector bool short __a, vector bool short __b, vector unsigned char __c)
-{
+static vector bool short __ATTRS_o_ai vec_perm(vector bool short __a,
+ vector bool short __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector bool short)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector bool short)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector bool short)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector bool short)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector pixel __ATTRS_o_ai
-vec_perm(vector pixel __a, vector pixel __b, vector unsigned char __c)
-{
+static vector pixel __ATTRS_o_ai vec_perm(vector pixel __a, vector pixel __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector pixel)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector pixel)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector pixel)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector pixel)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector int __ATTRS_o_ai
-vec_perm(vector int __a, vector int __b, vector unsigned char __c)
-{
+static vector int __ATTRS_o_ai vec_perm(vector signed int __a,
+ vector signed int __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector int)__builtin_altivec_vperm_4si(__b, __a, __d);
+ return (vector signed int)__builtin_altivec_vperm_4si(__b, __a, __d);
#else
- return (vector int)__builtin_altivec_vperm_4si(__a, __b, __c);
+ return (vector signed int)__builtin_altivec_vperm_4si(__a, __b, __c);
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_perm(vector unsigned int __a, vector unsigned int __b, vector unsigned char __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_perm(vector unsigned int __a,
+ vector unsigned int __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector unsigned int)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector unsigned int)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector bool int __ATTRS_o_ai
-vec_perm(vector bool int __a, vector bool int __b, vector unsigned char __c)
-{
+static vector bool int __ATTRS_o_ai vec_perm(vector bool int __a,
+ vector bool int __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector bool int)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector bool int)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector bool int)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector bool int)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
-static vector float __ATTRS_o_ai
-vec_perm(vector float __a, vector float __b, vector unsigned char __c)
-{
+static vector float __ATTRS_o_ai vec_perm(vector float __a, vector float __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector float)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector float)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
#else
- return (vector float)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector float)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
#ifdef __VSX__
-static vector long long __ATTRS_o_ai
-vec_perm(vector long long __a, vector long long __b, vector unsigned char __c)
-{
+static vector long long __ATTRS_o_ai vec_perm(vector signed long long __a,
+ vector signed long long __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector long long)__builtin_altivec_vperm_4si(__b, __a, __d);
+ return (vector signed long long)__builtin_altivec_vperm_4si(
+ (vector int)__b, (vector int)__a, __d);
#else
- return (vector long long)__builtin_altivec_vperm_4si(__a, __b, __c);
+ return (vector signed long long)__builtin_altivec_vperm_4si(
+ (vector int)__a, (vector int)__b, __c);
#endif
}
static vector unsigned long long __ATTRS_o_ai
vec_perm(vector unsigned long long __a, vector unsigned long long __b,
- vector unsigned char __c)
-{
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector unsigned long long)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector unsigned long long)__builtin_altivec_vperm_4si(
+ (vector int)__b, (vector int)__a, __d);
#else
- return (vector unsigned long long)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector unsigned long long)__builtin_altivec_vperm_4si(
+ (vector int)__a, (vector int)__b, __c);
#endif
}
-static vector double __ATTRS_o_ai
-vec_perm(vector double __a, vector double __b, vector unsigned char __c)
-{
+static vector bool long long __ATTRS_o_ai
+vec_perm(vector bool long long __a, vector bool long long __b,
+ vector unsigned char __c) {
#ifdef __LITTLE_ENDIAN__
- vector unsigned char __d = {255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255};
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
__d = vec_xor(__c, __d);
- return (vector double)
- __builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d);
+ return (vector bool long long)__builtin_altivec_vperm_4si(
+ (vector int)__b, (vector int)__a, __d);
#else
- return (vector double)
- __builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c);
+ return (vector bool long long)__builtin_altivec_vperm_4si(
+ (vector int)__a, (vector int)__b, __c);
+#endif
+}
+
+static vector double __ATTRS_o_ai vec_perm(vector double __a, vector double __b,
+ vector unsigned char __c) {
+#ifdef __LITTLE_ENDIAN__
+ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
+ __d = vec_xor(__c, __d);
+ return (vector double)__builtin_altivec_vperm_4si((vector int)__b,
+ (vector int)__a, __d);
+#else
+ return (vector double)__builtin_altivec_vperm_4si((vector int)__a,
+ (vector int)__b, __c);
#endif
}
#endif
/* vec_vperm */
-static vector signed char __ATTRS_o_ai
-vec_vperm(vector signed char __a, vector signed char __b, vector unsigned char __c)
-{
+static vector signed char __ATTRS_o_ai vec_vperm(vector signed char __a,
+ vector signed char __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vperm(vector unsigned char __a,
- vector unsigned char __b,
- vector unsigned char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_vperm(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector bool char __ATTRS_o_ai
-vec_vperm(vector bool char __a, vector bool char __b, vector unsigned char __c)
-{
+static vector bool char __ATTRS_o_ai vec_vperm(vector bool char __a,
+ vector bool char __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector short __ATTRS_o_ai
-vec_vperm(vector short __a, vector short __b, vector unsigned char __c)
-{
+static vector short __ATTRS_o_ai vec_vperm(vector short __a, vector short __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vperm(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned char __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_vperm(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector bool short __ATTRS_o_ai
-vec_vperm(vector bool short __a, vector bool short __b, vector unsigned char __c)
-{
+static vector bool short __ATTRS_o_ai vec_vperm(vector bool short __a,
+ vector bool short __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector pixel __ATTRS_o_ai
-vec_vperm(vector pixel __a, vector pixel __b, vector unsigned char __c)
-{
+static vector pixel __ATTRS_o_ai vec_vperm(vector pixel __a, vector pixel __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector int __ATTRS_o_ai
-vec_vperm(vector int __a, vector int __b, vector unsigned char __c)
-{
+static vector int __ATTRS_o_ai vec_vperm(vector int __a, vector int __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vperm(vector unsigned int __a, vector unsigned int __b, vector unsigned char __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_vperm(vector unsigned int __a,
+ vector unsigned int __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector bool int __ATTRS_o_ai
-vec_vperm(vector bool int __a, vector bool int __b, vector unsigned char __c)
-{
+static vector bool int __ATTRS_o_ai vec_vperm(vector bool int __a,
+ vector bool int __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector float __ATTRS_o_ai
-vec_vperm(vector float __a, vector float __b, vector unsigned char __c)
-{
+static vector float __ATTRS_o_ai vec_vperm(vector float __a, vector float __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
#ifdef __VSX__
-static vector long long __ATTRS_o_ai
-vec_vperm(vector long long __a, vector long long __b, vector unsigned char __c)
-{
+static vector long long __ATTRS_o_ai vec_vperm(vector long long __a,
+ vector long long __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
static vector unsigned long long __ATTRS_o_ai
vec_vperm(vector unsigned long long __a, vector unsigned long long __b,
- vector unsigned char __c)
-{
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
-static vector double __ATTRS_o_ai
-vec_vperm(vector double __a, vector double __b, vector unsigned char __c)
-{
+static vector double __ATTRS_o_ai vec_vperm(vector double __a,
+ vector double __b,
+ vector unsigned char __c) {
return vec_perm(__a, __b, __c);
}
#endif
/* vec_re */
-static vector float __attribute__((__always_inline__))
-vec_re(vector float __a)
-{
+static vector float __ATTRS_o_ai
+vec_re(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvresp(__a);
+#else
return __builtin_altivec_vrefp(__a);
+#endif
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_re(vector double __a) {
+ return __builtin_vsx_xvredp(__a);
+}
+#endif
+
/* vec_vrefp */
static vector float __attribute__((__always_inline__))
-vec_vrefp(vector float __a)
-{
+vec_vrefp(vector float __a) {
return __builtin_altivec_vrefp(__a);
}
/* vec_rl */
-static vector signed char __ATTRS_o_ai
-vec_rl(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_rl(vector signed char __a,
+ vector unsigned char __b) {
return (vector signed char)__builtin_altivec_vrlb((vector char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_rl(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_rl(vector unsigned char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__builtin_altivec_vrlb((vector char)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_rl(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_rl(vector short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vrlh(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_rl(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_rl(vector unsigned short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__builtin_altivec_vrlh((vector short)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_rl(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_rl(vector int __a, vector unsigned int __b) {
return __builtin_altivec_vrlw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_rl(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_rl(vector unsigned int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__builtin_altivec_vrlw((vector int)__a, __b);
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_rl(vector signed long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vrld(__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_rl(vector unsigned long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_vrld(__a, __b);
+}
+#endif
+
/* vec_vrlb */
-static vector signed char __ATTRS_o_ai
-vec_vrlb(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vrlb(vector signed char __a,
+ vector unsigned char __b) {
return (vector signed char)__builtin_altivec_vrlb((vector char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vrlb(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vrlb(vector unsigned char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__builtin_altivec_vrlb((vector char)__a, __b);
}
/* vec_vrlh */
-static vector short __ATTRS_o_ai
-vec_vrlh(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vrlh(vector short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vrlh(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vrlh(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vrlh(vector unsigned short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__builtin_altivec_vrlh((vector short)__a, __b);
}
/* vec_vrlw */
-static vector int __ATTRS_o_ai
-vec_vrlw(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vrlw(vector int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vrlw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vrlw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vrlw(vector unsigned int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__builtin_altivec_vrlw((vector int)__a, __b);
}
/* vec_round */
-static vector float __attribute__((__always_inline__))
-vec_round(vector float __a)
-{
+static vector float __ATTRS_o_ai vec_round(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvrspi(__a);
+#else
return __builtin_altivec_vrfin(__a);
+#endif
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_round(vector double __a) {
+ return __builtin_vsx_xvrdpi(__a);
+}
+
+/* vec_rint */
+
+static vector float __ATTRS_o_ai
+vec_rint(vector float __a) {
+ return __builtin_vsx_xvrspic(__a);
+}
+
+static vector double __ATTRS_o_ai
+vec_rint(vector double __a) {
+ return __builtin_vsx_xvrdpic(__a);
}
+/* vec_nearbyint */
+
+static vector float __ATTRS_o_ai vec_nearbyint(vector float __a) {
+ return __builtin_vsx_xvrspi(__a);
+}
+
+static vector double __ATTRS_o_ai vec_nearbyint(vector double __a) {
+ return __builtin_vsx_xvrdpi(__a);
+}
+#endif
+
/* vec_vrfin */
static vector float __attribute__((__always_inline__))
-vec_vrfin(vector float __a)
-{
+vec_vrfin(vector float __a) {
return __builtin_altivec_vrfin(__a);
}
+/* vec_sqrt */
+
+#ifdef __VSX__
+static vector float __ATTRS_o_ai vec_sqrt(vector float __a) {
+ return __builtin_vsx_xvsqrtsp(__a);
+}
+
+static vector double __ATTRS_o_ai vec_sqrt(vector double __a) {
+ return __builtin_vsx_xvsqrtdp(__a);
+}
+#endif
+
/* vec_rsqrte */
-static __vector float __attribute__((__always_inline__))
-vec_rsqrte(vector float __a)
-{
+static vector float __ATTRS_o_ai
+vec_rsqrte(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvrsqrtesp(__a);
+#else
return __builtin_altivec_vrsqrtefp(__a);
+#endif
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_rsqrte(vector double __a) {
+ return __builtin_vsx_xvrsqrtedp(__a);
+}
+#endif
+
/* vec_vrsqrtefp */
static __vector float __attribute__((__always_inline__))
-vec_vrsqrtefp(vector float __a)
-{
+vec_vrsqrtefp(vector float __a) {
return __builtin_altivec_vrsqrtefp(__a);
}
@@ -5173,311 +6214,316 @@ vec_vrsqrtefp(vector float __a)
#define __builtin_altivec_vsel_4si vec_sel
-static vector signed char __ATTRS_o_ai
-vec_sel(vector signed char __a, vector signed char __b, vector unsigned char __c)
-{
+static vector signed char __ATTRS_o_ai vec_sel(vector signed char __a,
+ vector signed char __b,
+ vector unsigned char __c) {
return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c);
}
-static vector signed char __ATTRS_o_ai
-vec_sel(vector signed char __a, vector signed char __b, vector bool char __c)
-{
+static vector signed char __ATTRS_o_ai vec_sel(vector signed char __a,
+ vector signed char __b,
+ vector bool char __c) {
return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sel(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_sel(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned char __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sel(vector unsigned char __a, vector unsigned char __b, vector bool char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_sel(vector unsigned char __a,
+ vector unsigned char __b,
+ vector bool char __c) {
return (__a & ~(vector unsigned char)__c) | (__b & (vector unsigned char)__c);
}
-static vector bool char __ATTRS_o_ai
-vec_sel(vector bool char __a, vector bool char __b, vector unsigned char __c)
-{
+static vector bool char __ATTRS_o_ai vec_sel(vector bool char __a,
+ vector bool char __b,
+ vector unsigned char __c) {
return (__a & ~(vector bool char)__c) | (__b & (vector bool char)__c);
}
-static vector bool char __ATTRS_o_ai
-vec_sel(vector bool char __a, vector bool char __b, vector bool char __c)
-{
+static vector bool char __ATTRS_o_ai vec_sel(vector bool char __a,
+ vector bool char __b,
+ vector bool char __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector short __ATTRS_o_ai
-vec_sel(vector short __a, vector short __b, vector unsigned short __c)
-{
+static vector short __ATTRS_o_ai vec_sel(vector short __a, vector short __b,
+ vector unsigned short __c) {
return (__a & ~(vector short)__c) | (__b & (vector short)__c);
}
-static vector short __ATTRS_o_ai
-vec_sel(vector short __a, vector short __b, vector bool short __c)
-{
+static vector short __ATTRS_o_ai vec_sel(vector short __a, vector short __b,
+ vector bool short __c) {
return (__a & ~(vector short)__c) | (__b & (vector short)__c);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sel(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned short __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_sel(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned short __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sel(vector unsigned short __a, vector unsigned short __b, vector bool short __c)
-{
- return (__a & ~(vector unsigned short)__c) | (__b & (vector unsigned short)__c);
+static vector unsigned short __ATTRS_o_ai vec_sel(vector unsigned short __a,
+ vector unsigned short __b,
+ vector bool short __c) {
+ return (__a & ~(vector unsigned short)__c) |
+ (__b & (vector unsigned short)__c);
}
-static vector bool short __ATTRS_o_ai
-vec_sel(vector bool short __a, vector bool short __b, vector unsigned short __c)
-{
+static vector bool short __ATTRS_o_ai vec_sel(vector bool short __a,
+ vector bool short __b,
+ vector unsigned short __c) {
return (__a & ~(vector bool short)__c) | (__b & (vector bool short)__c);
}
-static vector bool short __ATTRS_o_ai
-vec_sel(vector bool short __a, vector bool short __b, vector bool short __c)
-{
+static vector bool short __ATTRS_o_ai vec_sel(vector bool short __a,
+ vector bool short __b,
+ vector bool short __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector int __ATTRS_o_ai
-vec_sel(vector int __a, vector int __b, vector unsigned int __c)
-{
+static vector int __ATTRS_o_ai vec_sel(vector int __a, vector int __b,
+ vector unsigned int __c) {
return (__a & ~(vector int)__c) | (__b & (vector int)__c);
}
-static vector int __ATTRS_o_ai
-vec_sel(vector int __a, vector int __b, vector bool int __c)
-{
+static vector int __ATTRS_o_ai vec_sel(vector int __a, vector int __b,
+ vector bool int __c) {
return (__a & ~(vector int)__c) | (__b & (vector int)__c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sel(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_sel(vector unsigned int __a,
+ vector unsigned int __b,
+ vector unsigned int __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sel(vector unsigned int __a, vector unsigned int __b, vector bool int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_sel(vector unsigned int __a,
+ vector unsigned int __b,
+ vector bool int __c) {
return (__a & ~(vector unsigned int)__c) | (__b & (vector unsigned int)__c);
}
-static vector bool int __ATTRS_o_ai
-vec_sel(vector bool int __a, vector bool int __b, vector unsigned int __c)
-{
+static vector bool int __ATTRS_o_ai vec_sel(vector bool int __a,
+ vector bool int __b,
+ vector unsigned int __c) {
return (__a & ~(vector bool int)__c) | (__b & (vector bool int)__c);
}
-static vector bool int __ATTRS_o_ai
-vec_sel(vector bool int __a, vector bool int __b, vector bool int __c)
-{
+static vector bool int __ATTRS_o_ai vec_sel(vector bool int __a,
+ vector bool int __b,
+ vector bool int __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector float __ATTRS_o_ai
-vec_sel(vector float __a, vector float __b, vector unsigned int __c)
-{
- vector int __res = ((vector int)__a & ~(vector int)__c)
- | ((vector int)__b & (vector int)__c);
+static vector float __ATTRS_o_ai vec_sel(vector float __a, vector float __b,
+ vector unsigned int __c) {
+ vector int __res = ((vector int)__a & ~(vector int)__c) |
+ ((vector int)__b & (vector int)__c);
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_sel(vector float __a, vector float __b, vector bool int __c)
-{
- vector int __res = ((vector int)__a & ~(vector int)__c)
- | ((vector int)__b & (vector int)__c);
+static vector float __ATTRS_o_ai vec_sel(vector float __a, vector float __b,
+ vector bool int __c) {
+ vector int __res = ((vector int)__a & ~(vector int)__c) |
+ ((vector int)__b & (vector int)__c);
return (vector float)__res;
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_sel(vector double __a, vector double __b,
+ vector bool long long __c) {
+ vector long long __res = ((vector long long)__a & ~(vector long long)__c) |
+ ((vector long long)__b & (vector long long)__c);
+ return (vector double)__res;
+}
+
+static vector double __ATTRS_o_ai vec_sel(vector double __a, vector double __b,
+ vector unsigned long long __c) {
+ vector long long __res = ((vector long long)__a & ~(vector long long)__c) |
+ ((vector long long)__b & (vector long long)__c);
+ return (vector double)__res;
+}
+#endif
+
/* vec_vsel */
-static vector signed char __ATTRS_o_ai
-vec_vsel(vector signed char __a, vector signed char __b, vector unsigned char __c)
-{
+static vector signed char __ATTRS_o_ai vec_vsel(vector signed char __a,
+ vector signed char __b,
+ vector unsigned char __c) {
return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c);
}
-static vector signed char __ATTRS_o_ai
-vec_vsel(vector signed char __a, vector signed char __b, vector bool char __c)
-{
+static vector signed char __ATTRS_o_ai vec_vsel(vector signed char __a,
+ vector signed char __b,
+ vector bool char __c) {
return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsel(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsel(vector unsigned char __a,
+ vector unsigned char __b,
+ vector unsigned char __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsel(vector unsigned char __a, vector unsigned char __b, vector bool char __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsel(vector unsigned char __a,
+ vector unsigned char __b,
+ vector bool char __c) {
return (__a & ~(vector unsigned char)__c) | (__b & (vector unsigned char)__c);
}
-static vector bool char __ATTRS_o_ai
-vec_vsel(vector bool char __a, vector bool char __b, vector unsigned char __c)
-{
+static vector bool char __ATTRS_o_ai vec_vsel(vector bool char __a,
+ vector bool char __b,
+ vector unsigned char __c) {
return (__a & ~(vector bool char)__c) | (__b & (vector bool char)__c);
}
-static vector bool char __ATTRS_o_ai
-vec_vsel(vector bool char __a, vector bool char __b, vector bool char __c)
-{
+static vector bool char __ATTRS_o_ai vec_vsel(vector bool char __a,
+ vector bool char __b,
+ vector bool char __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector short __ATTRS_o_ai
-vec_vsel(vector short __a, vector short __b, vector unsigned short __c)
-{
+static vector short __ATTRS_o_ai vec_vsel(vector short __a, vector short __b,
+ vector unsigned short __c) {
return (__a & ~(vector short)__c) | (__b & (vector short)__c);
}
-static vector short __ATTRS_o_ai
-vec_vsel(vector short __a, vector short __b, vector bool short __c)
-{
+static vector short __ATTRS_o_ai vec_vsel(vector short __a, vector short __b,
+ vector bool short __c) {
return (__a & ~(vector short)__c) | (__b & (vector short)__c);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsel(vector unsigned short __a,
- vector unsigned short __b,
- vector unsigned short __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsel(vector unsigned short __a,
+ vector unsigned short __b,
+ vector unsigned short __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsel(vector unsigned short __a, vector unsigned short __b, vector bool short __c)
-{
- return (__a & ~(vector unsigned short)__c) | (__b & (vector unsigned short)__c);
+static vector unsigned short __ATTRS_o_ai vec_vsel(vector unsigned short __a,
+ vector unsigned short __b,
+ vector bool short __c) {
+ return (__a & ~(vector unsigned short)__c) |
+ (__b & (vector unsigned short)__c);
}
-static vector bool short __ATTRS_o_ai
-vec_vsel(vector bool short __a, vector bool short __b, vector unsigned short __c)
-{
+static vector bool short __ATTRS_o_ai vec_vsel(vector bool short __a,
+ vector bool short __b,
+ vector unsigned short __c) {
return (__a & ~(vector bool short)__c) | (__b & (vector bool short)__c);
}
-static vector bool short __ATTRS_o_ai
-vec_vsel(vector bool short __a, vector bool short __b, vector bool short __c)
-{
+static vector bool short __ATTRS_o_ai vec_vsel(vector bool short __a,
+ vector bool short __b,
+ vector bool short __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector int __ATTRS_o_ai
-vec_vsel(vector int __a, vector int __b, vector unsigned int __c)
-{
+static vector int __ATTRS_o_ai vec_vsel(vector int __a, vector int __b,
+ vector unsigned int __c) {
return (__a & ~(vector int)__c) | (__b & (vector int)__c);
}
-static vector int __ATTRS_o_ai
-vec_vsel(vector int __a, vector int __b, vector bool int __c)
-{
+static vector int __ATTRS_o_ai vec_vsel(vector int __a, vector int __b,
+ vector bool int __c) {
return (__a & ~(vector int)__c) | (__b & (vector int)__c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsel(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsel(vector unsigned int __a,
+ vector unsigned int __b,
+ vector unsigned int __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsel(vector unsigned int __a, vector unsigned int __b, vector bool int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsel(vector unsigned int __a,
+ vector unsigned int __b,
+ vector bool int __c) {
return (__a & ~(vector unsigned int)__c) | (__b & (vector unsigned int)__c);
}
-static vector bool int __ATTRS_o_ai
-vec_vsel(vector bool int __a, vector bool int __b, vector unsigned int __c)
-{
+static vector bool int __ATTRS_o_ai vec_vsel(vector bool int __a,
+ vector bool int __b,
+ vector unsigned int __c) {
return (__a & ~(vector bool int)__c) | (__b & (vector bool int)__c);
}
-static vector bool int __ATTRS_o_ai
-vec_vsel(vector bool int __a, vector bool int __b, vector bool int __c)
-{
+static vector bool int __ATTRS_o_ai vec_vsel(vector bool int __a,
+ vector bool int __b,
+ vector bool int __c) {
return (__a & ~__c) | (__b & __c);
}
-static vector float __ATTRS_o_ai
-vec_vsel(vector float __a, vector float __b, vector unsigned int __c)
-{
- vector int __res = ((vector int)__a & ~(vector int)__c)
- | ((vector int)__b & (vector int)__c);
+static vector float __ATTRS_o_ai vec_vsel(vector float __a, vector float __b,
+ vector unsigned int __c) {
+ vector int __res = ((vector int)__a & ~(vector int)__c) |
+ ((vector int)__b & (vector int)__c);
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vsel(vector float __a, vector float __b, vector bool int __c)
-{
- vector int __res = ((vector int)__a & ~(vector int)__c)
- | ((vector int)__b & (vector int)__c);
+static vector float __ATTRS_o_ai vec_vsel(vector float __a, vector float __b,
+ vector bool int __c) {
+ vector int __res = ((vector int)__a & ~(vector int)__c) |
+ ((vector int)__b & (vector int)__c);
return (vector float)__res;
}
/* vec_sl */
-static vector signed char __ATTRS_o_ai
-vec_sl(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_sl(vector signed char __a,
+ vector unsigned char __b) {
return __a << (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_sl(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sl(vector unsigned char __a,
+ vector unsigned char __b) {
return __a << __b;
}
-static vector short __ATTRS_o_ai
-vec_sl(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_sl(vector short __a,
+ vector unsigned short __b) {
return __a << (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_sl(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sl(vector unsigned short __a,
+ vector unsigned short __b) {
return __a << __b;
}
-static vector int __ATTRS_o_ai
-vec_sl(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_sl(vector int __a, vector unsigned int __b) {
return __a << (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_sl(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sl(vector unsigned int __a,
+ vector unsigned int __b) {
return __a << __b;
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_sl(vector signed long long __a, vector unsigned long long __b) {
+ return __a << (vector long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_sl(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a << __b;
+}
+#endif
+
/* vec_vslb */
#define __builtin_altivec_vslb vec_vslb
-static vector signed char __ATTRS_o_ai
-vec_vslb(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vslb(vector signed char __a,
+ vector unsigned char __b) {
return vec_sl(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vslb(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vslb(vector unsigned char __a,
+ vector unsigned char __b) {
return vec_sl(__a, __b);
}
@@ -5485,15 +6531,13 @@ vec_vslb(vector unsigned char __a, vector unsigned char __b)
#define __builtin_altivec_vslh vec_vslh
-static vector short __ATTRS_o_ai
-vec_vslh(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vslh(vector short __a,
+ vector unsigned short __b) {
return vec_sl(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vslh(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vslh(vector unsigned short __a,
+ vector unsigned short __b) {
return vec_sl(__a, __b);
}
@@ -5501,15 +6545,13 @@ vec_vslh(vector unsigned short __a, vector unsigned short __b)
#define __builtin_altivec_vslw vec_vslw
-static vector int __ATTRS_o_ai
-vec_vslw(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vslw(vector int __a,
+ vector unsigned int __b) {
return vec_sl(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vslw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vslw(vector unsigned int __a,
+ vector unsigned int __b) {
return vec_sl(__a, __b);
}
@@ -5517,847 +6559,872 @@ vec_vslw(vector unsigned int __a, vector unsigned int __b)
#define __builtin_altivec_vsldoi_4si vec_sld
-static vector signed char __ATTRS_o_ai
-vec_sld(vector signed char __a, vector signed char __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned char __ATTRS_o_ai
-vec_sld(vector unsigned char __a, vector unsigned char __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector short __ATTRS_o_ai
-vec_sld(vector short __a, vector short __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned short __ATTRS_o_ai
-vec_sld(vector unsigned short __a, vector unsigned short __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector pixel __ATTRS_o_ai
-vec_sld(vector pixel __a, vector pixel __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector int __ATTRS_o_ai
-vec_sld(vector int __a, vector int __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned int __ATTRS_o_ai
-vec_sld(vector unsigned int __a, vector unsigned int __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector float __ATTRS_o_ai
-vec_sld(vector float __a, vector float __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
+static vector signed char __ATTRS_o_ai vec_sld(vector signed char __a,
+ vector signed char __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector unsigned char __ATTRS_o_ai vec_sld(vector unsigned char __a,
+ vector unsigned char __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector bool char __ATTRS_o_ai vec_sld(vector bool char __a,
+ vector bool char __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector signed short __ATTRS_o_ai vec_sld(vector signed short __a,
+ vector signed short __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector unsigned short __ATTRS_o_ai vec_sld(vector unsigned short __a,
+ vector unsigned short __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector bool short __ATTRS_o_ai vec_sld(vector bool short __a,
+ vector bool short __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector pixel __ATTRS_o_ai vec_sld(vector pixel __a, vector pixel __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector signed int __ATTRS_o_ai vec_sld(vector signed int __a,
+ vector signed int __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector unsigned int __ATTRS_o_ai vec_sld(vector unsigned int __a,
+ vector unsigned int __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector bool int __ATTRS_o_ai vec_sld(vector bool int __a,
+ vector bool int __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+}
+
+static vector float __ATTRS_o_ai vec_sld(vector float __a, vector float __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
}
/* vec_vsldoi */
-static vector signed char __ATTRS_o_ai
-vec_vsldoi(vector signed char __a, vector signed char __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned char __ATTRS_o_ai
-vec_vsldoi(vector unsigned char __a, vector unsigned char __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector short __ATTRS_o_ai
-vec_vsldoi(vector short __a, vector short __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned short __ATTRS_o_ai
-vec_vsldoi(vector unsigned short __a, vector unsigned short __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector pixel __ATTRS_o_ai
-vec_vsldoi(vector pixel __a, vector pixel __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector int __ATTRS_o_ai
-vec_vsldoi(vector int __a, vector int __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector unsigned int __ATTRS_o_ai
-vec_vsldoi(vector unsigned int __a, vector unsigned int __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
-}
-
-static vector float __ATTRS_o_ai
-vec_vsldoi(vector float __a, vector float __b, unsigned char __c)
-{
- return vec_perm(__a, __b, (vector unsigned char)
- (__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
- __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15));
+static vector signed char __ATTRS_o_ai vec_vsldoi(vector signed char __a,
+ vector signed char __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector unsigned char __ATTRS_o_ai vec_vsldoi(vector unsigned char __a,
+ vector unsigned char __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector short __ATTRS_o_ai vec_vsldoi(vector short __a, vector short __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector unsigned short __ATTRS_o_ai vec_vsldoi(vector unsigned short __a,
+ vector unsigned short __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector pixel __ATTRS_o_ai vec_vsldoi(vector pixel __a, vector pixel __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector int __ATTRS_o_ai vec_vsldoi(vector int __a, vector int __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector unsigned int __ATTRS_o_ai vec_vsldoi(vector unsigned int __a,
+ vector unsigned int __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
+}
+
+static vector float __ATTRS_o_ai vec_vsldoi(vector float __a, vector float __b,
+ unsigned char __c) {
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__c, __c + 1, __c + 2, __c + 3, __c + 4, __c + 5,
+ __c + 6, __c + 7, __c + 8, __c + 9, __c + 10,
+ __c + 11, __c + 12, __c + 13, __c + 14, __c + 15));
}
/* vec_sll */
-static vector signed char __ATTRS_o_ai
-vec_sll(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_sll(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_sll(vector signed char __a, vector unsigned short __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_sll(vector signed char __a,
+ vector unsigned short __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_sll(vector signed char __a, vector unsigned int __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_sll(vector signed char __a,
+ vector unsigned int __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sll(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sll(vector unsigned char __a, vector unsigned short __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a,
+ vector unsigned short __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sll(vector unsigned char __a, vector unsigned int __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a,
+ vector unsigned int __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_sll(vector bool char __a, vector unsigned char __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_sll(vector bool char __a,
+ vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_sll(vector bool char __a, vector unsigned short __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_sll(vector bool char __a,
+ vector unsigned short __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_sll(vector bool char __a, vector unsigned int __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_sll(vector bool char __a,
+ vector unsigned int __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_sll(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_sll(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_sll(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_sll(vector short __a,
+ vector unsigned short __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_sll(vector short __a, vector unsigned int __b)
-{
+static vector short __ATTRS_o_ai vec_sll(vector short __a,
+ vector unsigned int __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sll(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sll(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sll(vector unsigned short __a, vector unsigned int __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a,
+ vector unsigned int __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_sll(vector bool short __a, vector unsigned char __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_sll(vector bool short __a,
+ vector unsigned char __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_sll(vector bool short __a, vector unsigned short __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_sll(vector bool short __a,
+ vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_sll(vector bool short __a, vector unsigned int __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_sll(vector bool short __a,
+ vector unsigned int __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_sll(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_sll(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_sll(vector pixel __a, vector unsigned short __b)
-{
+static vector pixel __ATTRS_o_ai vec_sll(vector pixel __a,
+ vector unsigned short __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_sll(vector pixel __a, vector unsigned int __b)
-{
+static vector pixel __ATTRS_o_ai vec_sll(vector pixel __a,
+ vector unsigned int __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_sll(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_sll(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_sll(vector int __a, vector unsigned short __b)
-{
+static vector int __ATTRS_o_ai vec_sll(vector int __a,
+ vector unsigned short __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_sll(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_sll(vector int __a,
+ vector unsigned int __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sll(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sll(vector unsigned int __a, vector unsigned short __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a,
+ vector unsigned short __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sll(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a,
+ vector unsigned int __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_sll(vector bool int __a, vector unsigned char __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_sll(vector bool int __a,
+ vector unsigned char __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_sll(vector bool int __a, vector unsigned short __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_sll(vector bool int __a,
+ vector unsigned short __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_sll(vector bool int __a, vector unsigned int __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_sll(vector bool int __a,
+ vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
/* vec_vsl */
-static vector signed char __ATTRS_o_ai
-vec_vsl(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsl(vector signed char __a, vector unsigned short __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a,
+ vector unsigned short __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsl(vector signed char __a, vector unsigned int __b)
-{
- return (vector signed char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a,
+ vector unsigned int __b) {
+ return (vector signed char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsl(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsl(vector unsigned char __a, vector unsigned short __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a,
+ vector unsigned short __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsl(vector unsigned char __a, vector unsigned int __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a,
+ vector unsigned int __b) {
+ return (vector unsigned char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsl(vector bool char __a, vector unsigned char __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a,
+ vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsl(vector bool char __a, vector unsigned short __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a,
+ vector unsigned short __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsl(vector bool char __a, vector unsigned int __b)
-{
- return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a,
+ vector unsigned int __b) {
+ return (vector bool char)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsl(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_vsl(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsl(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vsl(vector short __a,
+ vector unsigned short __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsl(vector short __a, vector unsigned int __b)
-{
+static vector short __ATTRS_o_ai vec_vsl(vector short __a,
+ vector unsigned int __b) {
return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsl(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsl(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsl(vector unsigned short __a, vector unsigned int __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a,
+ vector unsigned int __b) {
+ return (vector unsigned short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsl(vector bool short __a, vector unsigned char __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a,
+ vector unsigned char __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsl(vector bool short __a, vector unsigned short __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a,
+ vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsl(vector bool short __a, vector unsigned int __b)
-{
- return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a,
+ vector unsigned int __b) {
+ return (vector bool short)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsl(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsl(vector pixel __a, vector unsigned short __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a,
+ vector unsigned short __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsl(vector pixel __a, vector unsigned int __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a,
+ vector unsigned int __b) {
return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsl(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_vsl(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsl(vector int __a, vector unsigned short __b)
-{
+static vector int __ATTRS_o_ai vec_vsl(vector int __a,
+ vector unsigned short __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsl(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vsl(vector int __a,
+ vector unsigned int __b) {
return (vector int)__builtin_altivec_vsl(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsl(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsl(vector unsigned int __a, vector unsigned short __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a,
+ vector unsigned short __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsl(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a,
+ vector unsigned int __b) {
+ return (vector unsigned int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsl(vector bool int __a, vector unsigned char __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a,
+ vector unsigned char __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsl(vector bool int __a, vector unsigned short __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a,
+ vector unsigned short __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsl(vector bool int __a, vector unsigned int __b)
-{
- return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a,
+ vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
}
/* vec_slo */
-static vector signed char __ATTRS_o_ai
-vec_slo(vector signed char __a, vector signed char __b)
-{
- return (vector signed char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_slo(vector signed char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_slo(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_slo(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_slo(vector unsigned char __a, vector signed char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_slo(vector unsigned char __a,
+ vector signed char __b) {
+ return (vector unsigned char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_slo(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_slo(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_slo(vector short __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_slo(vector short __a,
+ vector signed char __b) {
return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_slo(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_slo(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_slo(vector unsigned short __a, vector signed char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_slo(vector unsigned short __a,
+ vector signed char __b) {
+ return (vector unsigned short)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_slo(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_slo(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_slo(vector pixel __a, vector signed char __b)
-{
+static vector pixel __ATTRS_o_ai vec_slo(vector pixel __a,
+ vector signed char __b) {
return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_slo(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_slo(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_slo(vector int __a, vector signed char __b)
-{
+static vector int __ATTRS_o_ai vec_slo(vector int __a, vector signed char __b) {
return (vector int)__builtin_altivec_vslo(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_slo(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_slo(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vslo(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_slo(vector unsigned int __a, vector signed char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_slo(vector unsigned int __a,
+ vector signed char __b) {
+ return (vector unsigned int)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_slo(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_slo(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_slo(vector float __a, vector signed char __b)
-{
+static vector float __ATTRS_o_ai vec_slo(vector float __a,
+ vector signed char __b) {
return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_slo(vector float __a, vector unsigned char __b)
-{
+static vector float __ATTRS_o_ai vec_slo(vector float __a,
+ vector unsigned char __b) {
return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
/* vec_vslo */
-static vector signed char __ATTRS_o_ai
-vec_vslo(vector signed char __a, vector signed char __b)
-{
- return (vector signed char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vslo(vector signed char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vslo(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vslo(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vslo(vector unsigned char __a, vector signed char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vslo(vector unsigned char __a,
+ vector signed char __b) {
+ return (vector unsigned char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vslo(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vslo(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vslo(vector short __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_vslo(vector short __a,
+ vector signed char __b) {
return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vslo(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_vslo(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vslo(vector unsigned short __a, vector signed char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vslo(vector unsigned short __a,
+ vector signed char __b) {
+ return (vector unsigned short)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vslo(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vslo(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vslo(vector pixel __a, vector signed char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vslo(vector pixel __a,
+ vector signed char __b) {
return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vslo(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vslo(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vslo(vector int __a, vector signed char __b)
-{
+static vector int __ATTRS_o_ai vec_vslo(vector int __a,
+ vector signed char __b) {
return (vector int)__builtin_altivec_vslo(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vslo(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_vslo(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vslo(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vslo(vector unsigned int __a, vector signed char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vslo(vector unsigned int __a,
+ vector signed char __b) {
+ return (vector unsigned int)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vslo(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vslo((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vslo(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_vslo(vector float __a, vector signed char __b)
-{
+static vector float __ATTRS_o_ai vec_vslo(vector float __a,
+ vector signed char __b) {
return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_vslo(vector float __a, vector unsigned char __b)
-{
+static vector float __ATTRS_o_ai vec_vslo(vector float __a,
+ vector unsigned char __b) {
return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
/* vec_splat */
-static vector signed char __ATTRS_o_ai
-vec_splat(vector signed char __a, unsigned char __b)
-{
- return vec_perm(__a, __a, (vector unsigned char)(__b));
+static vector signed char __ATTRS_o_ai vec_splat(vector signed char __a,
+ unsigned const int __b) {
+ return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F));
}
-static vector unsigned char __ATTRS_o_ai
-vec_splat(vector unsigned char __a, unsigned char __b)
-{
- return vec_perm(__a, __a, (vector unsigned char)(__b));
+static vector unsigned char __ATTRS_o_ai vec_splat(vector unsigned char __a,
+ unsigned const int __b) {
+ return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F));
}
-static vector bool char __ATTRS_o_ai
-vec_splat(vector bool char __a, unsigned char __b)
-{
- return vec_perm(__a, __a, (vector unsigned char)(__b));
+static vector bool char __ATTRS_o_ai vec_splat(vector bool char __a,
+ unsigned const int __b) {
+ return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F));
}
-static vector short __ATTRS_o_ai
-vec_splat(vector short __a, unsigned char __b)
-{
- __b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+static vector signed short __ATTRS_o_ai vec_splat(vector signed short __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x07) * 2;
+ unsigned char b1 = b0 + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1,
+ b0, b1, b0, b1, b0, b1, b0, b1));
}
-static vector unsigned short __ATTRS_o_ai
-vec_splat(vector unsigned short __a, unsigned char __b)
-{
- __b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+static vector unsigned short __ATTRS_o_ai vec_splat(vector unsigned short __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x07) * 2;
+ unsigned char b1 = b0 + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1,
+ b0, b1, b0, b1, b0, b1, b0, b1));
}
-static vector bool short __ATTRS_o_ai
-vec_splat(vector bool short __a, unsigned char __b)
-{
- __b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+static vector bool short __ATTRS_o_ai vec_splat(vector bool short __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x07) * 2;
+ unsigned char b1 = b0 + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1,
+ b0, b1, b0, b1, b0, b1, b0, b1));
}
-static vector pixel __ATTRS_o_ai
-vec_splat(vector pixel __a, unsigned char __b)
-{
- __b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+static vector pixel __ATTRS_o_ai vec_splat(vector pixel __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x07) * 2;
+ unsigned char b1 = b0 + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1,
+ b0, b1, b0, b1, b0, b1, b0, b1));
}
-static vector int __ATTRS_o_ai
-vec_splat(vector int __a, unsigned char __b)
-{
- __b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+static vector signed int __ATTRS_o_ai vec_splat(vector signed int __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x03) * 4;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0,
+ b1, b2, b3, b0, b1, b2, b3));
}
-static vector unsigned int __ATTRS_o_ai
-vec_splat(vector unsigned int __a, unsigned char __b)
-{
- __b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+static vector unsigned int __ATTRS_o_ai vec_splat(vector unsigned int __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x03) * 4;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0,
+ b1, b2, b3, b0, b1, b2, b3));
}
-static vector bool int __ATTRS_o_ai
-vec_splat(vector bool int __a, unsigned char __b)
-{
- __b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+static vector bool int __ATTRS_o_ai vec_splat(vector bool int __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x03) * 4;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0,
+ b1, b2, b3, b0, b1, b2, b3));
}
-static vector float __ATTRS_o_ai
-vec_splat(vector float __a, unsigned char __b)
-{
- __b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+static vector float __ATTRS_o_ai vec_splat(vector float __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x03) * 4;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0,
+ b1, b2, b3, b0, b1, b2, b3));
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_splat(vector double __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x01) * 8;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4,
+ b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7,
+ b0, b1, b2, b3, b4, b5, b6, b7));
+}
+static vector bool long long __ATTRS_o_ai vec_splat(vector bool long long __a,
+ unsigned const int __b) {
+ unsigned char b0 = (__b & 0x01) * 8;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4,
+ b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7,
+ b0, b1, b2, b3, b4, b5, b6, b7));
+}
+static vector signed long long __ATTRS_o_ai
+vec_splat(vector signed long long __a, unsigned const int __b) {
+ unsigned char b0 = (__b & 0x01) * 8;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4,
+ b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7,
+ b0, b1, b2, b3, b4, b5, b6, b7));
}
+static vector unsigned long long __ATTRS_o_ai
+vec_splat(vector unsigned long long __a, unsigned const int __b) {
+ unsigned char b0 = (__b & 0x01) * 8;
+ unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4,
+ b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7,
+ b0, b1, b2, b3, b4, b5, b6, b7));
+}
+#endif
/* vec_vspltb */
#define __builtin_altivec_vspltb vec_vspltb
-static vector signed char __ATTRS_o_ai
-vec_vspltb(vector signed char __a, unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vspltb(vector signed char __a,
+ unsigned char __b) {
return vec_perm(__a, __a, (vector unsigned char)(__b));
}
-static vector unsigned char __ATTRS_o_ai
-vec_vspltb(vector unsigned char __a, unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vspltb(vector unsigned char __a,
+ unsigned char __b) {
return vec_perm(__a, __a, (vector unsigned char)(__b));
}
-static vector bool char __ATTRS_o_ai
-vec_vspltb(vector bool char __a, unsigned char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vspltb(vector bool char __a,
+ unsigned char __b) {
return vec_perm(__a, __a, (vector unsigned char)(__b));
}
@@ -6365,80 +7432,79 @@ vec_vspltb(vector bool char __a, unsigned char __b)
#define __builtin_altivec_vsplth vec_vsplth
-static vector short __ATTRS_o_ai
-vec_vsplth(vector short __a, unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_vsplth(vector short __a,
+ unsigned char __b) {
__b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+ unsigned char b1 = __b + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1,
+ __b, b1, __b, b1, __b, b1, __b, b1));
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsplth(vector unsigned short __a, unsigned char __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsplth(vector unsigned short __a,
+ unsigned char __b) {
__b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+ unsigned char b1 = __b + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1,
+ __b, b1, __b, b1, __b, b1, __b, b1));
}
-static vector bool short __ATTRS_o_ai
-vec_vsplth(vector bool short __a, unsigned char __b)
-{
+static vector bool short __ATTRS_o_ai vec_vsplth(vector bool short __a,
+ unsigned char __b) {
__b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+ unsigned char b1 = __b + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1,
+ __b, b1, __b, b1, __b, b1, __b, b1));
}
-static vector pixel __ATTRS_o_ai
-vec_vsplth(vector pixel __a, unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsplth(vector pixel __a,
+ unsigned char __b) {
__b *= 2;
- unsigned char b1=__b+1;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1));
+ unsigned char b1 = __b + 1;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1,
+ __b, b1, __b, b1, __b, b1, __b, b1));
}
/* vec_vspltw */
#define __builtin_altivec_vspltw vec_vspltw
-static vector int __ATTRS_o_ai
-vec_vspltw(vector int __a, unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_vspltw(vector int __a, unsigned char __b) {
__b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+ unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b,
+ b1, b2, b3, __b, b1, b2, b3));
}
-static vector unsigned int __ATTRS_o_ai
-vec_vspltw(vector unsigned int __a, unsigned char __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vspltw(vector unsigned int __a,
+ unsigned char __b) {
__b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+ unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b,
+ b1, b2, b3, __b, b1, b2, b3));
}
-static vector bool int __ATTRS_o_ai
-vec_vspltw(vector bool int __a, unsigned char __b)
-{
+static vector bool int __ATTRS_o_ai vec_vspltw(vector bool int __a,
+ unsigned char __b) {
__b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+ unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b,
+ b1, b2, b3, __b, b1, b2, b3));
}
-static vector float __ATTRS_o_ai
-vec_vspltw(vector float __a, unsigned char __b)
-{
+static vector float __ATTRS_o_ai vec_vspltw(vector float __a,
+ unsigned char __b) {
__b *= 4;
- unsigned char b1=__b+1, b2=__b+2, b3=__b+3;
- return vec_perm(__a, __a, (vector unsigned char)
- (__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3));
+ unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3;
+ return vec_perm(__a, __a,
+ (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b,
+ b1, b2, b3, __b, b1, b2, b3));
}
/* vec_splat_s8 */
@@ -6446,18 +7512,14 @@ vec_vspltw(vector float __a, unsigned char __b)
#define __builtin_altivec_vspltisb vec_splat_s8
// FIXME: parameter should be treated as 5-bit signed literal
-static vector signed char __ATTRS_o_ai
-vec_splat_s8(signed char __a)
-{
+static vector signed char __ATTRS_o_ai vec_splat_s8(signed char __a) {
return (vector signed char)(__a);
}
/* vec_vspltisb */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector signed char __ATTRS_o_ai
-vec_vspltisb(signed char __a)
-{
+static vector signed char __ATTRS_o_ai vec_vspltisb(signed char __a) {
return (vector signed char)(__a);
}
@@ -6466,18 +7528,14 @@ vec_vspltisb(signed char __a)
#define __builtin_altivec_vspltish vec_splat_s16
// FIXME: parameter should be treated as 5-bit signed literal
-static vector short __ATTRS_o_ai
-vec_splat_s16(signed char __a)
-{
+static vector short __ATTRS_o_ai vec_splat_s16(signed char __a) {
return (vector short)(__a);
}
/* vec_vspltish */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector short __ATTRS_o_ai
-vec_vspltish(signed char __a)
-{
+static vector short __ATTRS_o_ai vec_vspltish(signed char __a) {
return (vector short)(__a);
}
@@ -6486,99 +7544,97 @@ vec_vspltish(signed char __a)
#define __builtin_altivec_vspltisw vec_splat_s32
// FIXME: parameter should be treated as 5-bit signed literal
-static vector int __ATTRS_o_ai
-vec_splat_s32(signed char __a)
-{
+static vector int __ATTRS_o_ai vec_splat_s32(signed char __a) {
return (vector int)(__a);
}
/* vec_vspltisw */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector int __ATTRS_o_ai
-vec_vspltisw(signed char __a)
-{
+static vector int __ATTRS_o_ai vec_vspltisw(signed char __a) {
return (vector int)(__a);
}
/* vec_splat_u8 */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector unsigned char __ATTRS_o_ai
-vec_splat_u8(unsigned char __a)
-{
+static vector unsigned char __ATTRS_o_ai vec_splat_u8(unsigned char __a) {
return (vector unsigned char)(__a);
}
/* vec_splat_u16 */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector unsigned short __ATTRS_o_ai
-vec_splat_u16(signed char __a)
-{
+static vector unsigned short __ATTRS_o_ai vec_splat_u16(signed char __a) {
return (vector unsigned short)(__a);
}
/* vec_splat_u32 */
// FIXME: parameter should be treated as 5-bit signed literal
-static vector unsigned int __ATTRS_o_ai
-vec_splat_u32(signed char __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_splat_u32(signed char __a) {
return (vector unsigned int)(__a);
}
/* vec_sr */
-static vector signed char __ATTRS_o_ai
-vec_sr(vector signed char __a, vector unsigned char __b)
-{
- return __a >> (vector signed char)__b;
+static vector signed char __ATTRS_o_ai vec_sr(vector signed char __a,
+ vector unsigned char __b) {
+ vector unsigned char __res = (vector unsigned char)__a >> __b;
+ return (vector signed char)__res;
}
-static vector unsigned char __ATTRS_o_ai
-vec_sr(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sr(vector unsigned char __a,
+ vector unsigned char __b) {
return __a >> __b;
}
-static vector short __ATTRS_o_ai
-vec_sr(vector short __a, vector unsigned short __b)
-{
- return __a >> (vector short)__b;
+static vector signed short __ATTRS_o_ai vec_sr(vector signed short __a,
+ vector unsigned short __b) {
+ vector unsigned short __res = (vector unsigned short)__a >> __b;
+ return (vector signed short)__res;
}
-static vector unsigned short __ATTRS_o_ai
-vec_sr(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sr(vector unsigned short __a,
+ vector unsigned short __b) {
return __a >> __b;
}
-static vector int __ATTRS_o_ai
-vec_sr(vector int __a, vector unsigned int __b)
-{
- return __a >> (vector int)__b;
+static vector signed int __ATTRS_o_ai vec_sr(vector signed int __a,
+ vector unsigned int __b) {
+ vector unsigned int __res = (vector unsigned int)__a >> __b;
+ return (vector signed int)__res;
}
-static vector unsigned int __ATTRS_o_ai
-vec_sr(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sr(vector unsigned int __a,
+ vector unsigned int __b) {
return __a >> __b;
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_sr(vector signed long long __a, vector unsigned long long __b) {
+ vector unsigned long long __res = (vector unsigned long long)__a >> __b;
+ return (vector signed long long)__res;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_sr(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a >> __b;
+}
+#endif
+
/* vec_vsrb */
#define __builtin_altivec_vsrb vec_vsrb
-static vector signed char __ATTRS_o_ai
-vec_vsrb(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsrb(vector signed char __a,
+ vector unsigned char __b) {
return __a >> (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsrb(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsrb(vector unsigned char __a,
+ vector unsigned char __b) {
return __a >> __b;
}
@@ -6586,15 +7642,13 @@ vec_vsrb(vector unsigned char __a, vector unsigned char __b)
#define __builtin_altivec_vsrh vec_vsrh
-static vector short __ATTRS_o_ai
-vec_vsrh(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vsrh(vector short __a,
+ vector unsigned short __b) {
return __a >> (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsrh(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsrh(vector unsigned short __a,
+ vector unsigned short __b) {
return __a >> __b;
}
@@ -6602,1671 +7656,1404 @@ vec_vsrh(vector unsigned short __a, vector unsigned short __b)
#define __builtin_altivec_vsrw vec_vsrw
-static vector int __ATTRS_o_ai
-vec_vsrw(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vsrw(vector int __a,
+ vector unsigned int __b) {
return __a >> (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsrw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsrw(vector unsigned int __a,
+ vector unsigned int __b) {
return __a >> __b;
}
/* vec_sra */
-static vector signed char __ATTRS_o_ai
-vec_sra(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_sra(vector signed char __a,
+ vector unsigned char __b) {
return (vector signed char)__builtin_altivec_vsrab((vector char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sra(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sra(vector unsigned char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__builtin_altivec_vsrab((vector char)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_sra(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_sra(vector short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vsrah(__a, (vector unsigned short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sra(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sra(vector unsigned short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__builtin_altivec_vsrah((vector short)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_sra(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_sra(vector int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsraw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sra(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sra(vector unsigned int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__builtin_altivec_vsraw((vector int)__a, __b);
}
+#ifdef __POWER8_VECTOR__
+static vector signed long long __ATTRS_o_ai
+vec_sra(vector signed long long __a, vector unsigned long long __b) {
+ return __a >> __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_sra(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)((vector signed long long)__a >> __b);
+}
+#endif
+
/* vec_vsrab */
-static vector signed char __ATTRS_o_ai
-vec_vsrab(vector signed char __a, vector unsigned char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsrab(vector signed char __a,
+ vector unsigned char __b) {
return (vector signed char)__builtin_altivec_vsrab((vector char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsrab(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsrab(vector unsigned char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__builtin_altivec_vsrab((vector char)__a, __b);
}
/* vec_vsrah */
-static vector short __ATTRS_o_ai
-vec_vsrah(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vsrah(vector short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vsrah(__a, (vector unsigned short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsrah(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsrah(vector unsigned short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__builtin_altivec_vsrah((vector short)__a, __b);
}
/* vec_vsraw */
-static vector int __ATTRS_o_ai
-vec_vsraw(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vsraw(vector int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsraw(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsraw(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsraw(vector unsigned int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__builtin_altivec_vsraw((vector int)__a, __b);
}
/* vec_srl */
-static vector signed char __ATTRS_o_ai
-vec_srl(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_srl(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_srl(vector signed char __a, vector unsigned short __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_srl(vector signed char __a,
+ vector unsigned short __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_srl(vector signed char __a, vector unsigned int __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_srl(vector signed char __a,
+ vector unsigned int __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_srl(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_srl(vector unsigned char __a, vector unsigned short __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a,
+ vector unsigned short __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_srl(vector unsigned char __a, vector unsigned int __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a,
+ vector unsigned int __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_srl(vector bool char __a, vector unsigned char __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_srl(vector bool char __a,
+ vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_srl(vector bool char __a, vector unsigned short __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_srl(vector bool char __a,
+ vector unsigned short __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_srl(vector bool char __a, vector unsigned int __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_srl(vector bool char __a,
+ vector unsigned int __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_srl(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_srl(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_srl(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_srl(vector short __a,
+ vector unsigned short __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_srl(vector short __a, vector unsigned int __b)
-{
+static vector short __ATTRS_o_ai vec_srl(vector short __a,
+ vector unsigned int __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_srl(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_srl(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_srl(vector unsigned short __a, vector unsigned int __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a,
+ vector unsigned int __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_srl(vector bool short __a, vector unsigned char __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_srl(vector bool short __a,
+ vector unsigned char __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_srl(vector bool short __a, vector unsigned short __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_srl(vector bool short __a,
+ vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_srl(vector bool short __a, vector unsigned int __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_srl(vector bool short __a,
+ vector unsigned int __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_srl(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_srl(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_srl(vector pixel __a, vector unsigned short __b)
-{
+static vector pixel __ATTRS_o_ai vec_srl(vector pixel __a,
+ vector unsigned short __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_srl(vector pixel __a, vector unsigned int __b)
-{
+static vector pixel __ATTRS_o_ai vec_srl(vector pixel __a,
+ vector unsigned int __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_srl(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_srl(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_srl(vector int __a, vector unsigned short __b)
-{
+static vector int __ATTRS_o_ai vec_srl(vector int __a,
+ vector unsigned short __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_srl(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_srl(vector int __a,
+ vector unsigned int __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_srl(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_srl(vector unsigned int __a, vector unsigned short __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a,
+ vector unsigned short __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_srl(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a,
+ vector unsigned int __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_srl(vector bool int __a, vector unsigned char __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_srl(vector bool int __a,
+ vector unsigned char __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_srl(vector bool int __a, vector unsigned short __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_srl(vector bool int __a,
+ vector unsigned short __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_srl(vector bool int __a, vector unsigned int __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_srl(vector bool int __a,
+ vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
/* vec_vsr */
-static vector signed char __ATTRS_o_ai
-vec_vsr(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsr(vector signed char __a, vector unsigned short __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a,
+ vector unsigned short __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsr(vector signed char __a, vector unsigned int __b)
-{
- return (vector signed char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a,
+ vector unsigned int __b) {
+ return (vector signed char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsr(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsr(vector unsigned char __a, vector unsigned short __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a,
+ vector unsigned short __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsr(vector unsigned char __a, vector unsigned int __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a,
+ vector unsigned int __b) {
+ return (vector unsigned char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsr(vector bool char __a, vector unsigned char __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a,
+ vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsr(vector bool char __a, vector unsigned short __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a,
+ vector unsigned short __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool char __ATTRS_o_ai
-vec_vsr(vector bool char __a, vector unsigned int __b)
-{
- return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a,
+ vector unsigned int __b) {
+ return (vector bool char)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsr(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_vsr(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsr(vector short __a, vector unsigned short __b)
-{
+static vector short __ATTRS_o_ai vec_vsr(vector short __a,
+ vector unsigned short __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsr(vector short __a, vector unsigned int __b)
-{
+static vector short __ATTRS_o_ai vec_vsr(vector short __a,
+ vector unsigned int __b) {
return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsr(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsr(vector unsigned short __a, vector unsigned short __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a,
+ vector unsigned short __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsr(vector unsigned short __a, vector unsigned int __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a,
+ vector unsigned int __b) {
+ return (vector unsigned short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsr(vector bool short __a, vector unsigned char __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a,
+ vector unsigned char __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsr(vector bool short __a, vector unsigned short __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a,
+ vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool short __ATTRS_o_ai
-vec_vsr(vector bool short __a, vector unsigned int __b)
-{
- return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a,
+ vector unsigned int __b) {
+ return (vector bool short)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsr(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsr(vector pixel __a, vector unsigned short __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a,
+ vector unsigned short __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsr(vector pixel __a, vector unsigned int __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a,
+ vector unsigned int __b) {
return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsr(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_vsr(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsr(vector int __a, vector unsigned short __b)
-{
+static vector int __ATTRS_o_ai vec_vsr(vector int __a,
+ vector unsigned short __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsr(vector int __a, vector unsigned int __b)
-{
+static vector int __ATTRS_o_ai vec_vsr(vector int __a,
+ vector unsigned int __b) {
return (vector int)__builtin_altivec_vsr(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsr(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsr(vector unsigned int __a, vector unsigned short __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a,
+ vector unsigned short __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsr(vector unsigned int __a, vector unsigned int __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a,
+ vector unsigned int __b) {
+ return (vector unsigned int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsr(vector bool int __a, vector unsigned char __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a,
+ vector unsigned char __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsr(vector bool int __a, vector unsigned short __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a,
+ vector unsigned short __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
-static vector bool int __ATTRS_o_ai
-vec_vsr(vector bool int __a, vector unsigned int __b)
-{
- return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b);
+static vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a,
+ vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
}
/* vec_sro */
-static vector signed char __ATTRS_o_ai
-vec_sro(vector signed char __a, vector signed char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_sro(vector signed char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_sro(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_sro(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sro(vector unsigned char __a, vector signed char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_sro(vector unsigned char __a,
+ vector signed char __b) {
+ return (vector unsigned char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_sro(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_sro(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_sro(vector short __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_sro(vector short __a,
+ vector signed char __b) {
return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_sro(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_sro(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sro(vector unsigned short __a, vector signed char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_sro(vector unsigned short __a,
+ vector signed char __b) {
+ return (vector unsigned short)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_sro(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_sro(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_sro(vector pixel __a, vector signed char __b)
-{
+static vector pixel __ATTRS_o_ai vec_sro(vector pixel __a,
+ vector signed char __b) {
return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_sro(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_sro(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_sro(vector int __a, vector signed char __b)
-{
+static vector int __ATTRS_o_ai vec_sro(vector int __a, vector signed char __b) {
return (vector int)__builtin_altivec_vsro(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_sro(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_sro(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsro(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sro(vector unsigned int __a, vector signed char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_sro(vector unsigned int __a,
+ vector signed char __b) {
+ return (vector unsigned int)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sro(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_sro(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_sro(vector float __a, vector signed char __b)
-{
+static vector float __ATTRS_o_ai vec_sro(vector float __a,
+ vector signed char __b) {
return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_sro(vector float __a, vector unsigned char __b)
-{
+static vector float __ATTRS_o_ai vec_sro(vector float __a,
+ vector unsigned char __b) {
return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
/* vec_vsro */
-static vector signed char __ATTRS_o_ai
-vec_vsro(vector signed char __a, vector signed char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsro(vector signed char __a,
+ vector signed char __b) {
+ return (vector signed char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsro(vector signed char __a, vector unsigned char __b)
-{
- return (vector signed char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector signed char __ATTRS_o_ai vec_vsro(vector signed char __a,
+ vector unsigned char __b) {
+ return (vector signed char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsro(vector unsigned char __a, vector signed char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsro(vector unsigned char __a,
+ vector signed char __b) {
+ return (vector unsigned char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsro(vector unsigned char __a, vector unsigned char __b)
-{
- return (vector unsigned char)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned char __ATTRS_o_ai vec_vsro(vector unsigned char __a,
+ vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsro(vector short __a, vector signed char __b)
-{
+static vector short __ATTRS_o_ai vec_vsro(vector short __a,
+ vector signed char __b) {
return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector short __ATTRS_o_ai
-vec_vsro(vector short __a, vector unsigned char __b)
-{
+static vector short __ATTRS_o_ai vec_vsro(vector short __a,
+ vector unsigned char __b) {
return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsro(vector unsigned short __a, vector signed char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsro(vector unsigned short __a,
+ vector signed char __b) {
+ return (vector unsigned short)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsro(vector unsigned short __a, vector unsigned char __b)
-{
- return (vector unsigned short)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned short __ATTRS_o_ai vec_vsro(vector unsigned short __a,
+ vector unsigned char __b) {
+ return (vector unsigned short)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsro(vector pixel __a, vector signed char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsro(vector pixel __a,
+ vector signed char __b) {
return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector pixel __ATTRS_o_ai
-vec_vsro(vector pixel __a, vector unsigned char __b)
-{
+static vector pixel __ATTRS_o_ai vec_vsro(vector pixel __a,
+ vector unsigned char __b) {
return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsro(vector int __a, vector signed char __b)
-{
+static vector int __ATTRS_o_ai vec_vsro(vector int __a,
+ vector signed char __b) {
return (vector int)__builtin_altivec_vsro(__a, (vector int)__b);
}
-static vector int __ATTRS_o_ai
-vec_vsro(vector int __a, vector unsigned char __b)
-{
+static vector int __ATTRS_o_ai vec_vsro(vector int __a,
+ vector unsigned char __b) {
return (vector int)__builtin_altivec_vsro(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsro(vector unsigned int __a, vector signed char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsro(vector unsigned int __a,
+ vector signed char __b) {
+ return (vector unsigned int)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsro(vector unsigned int __a, vector unsigned char __b)
-{
- return (vector unsigned int)
- __builtin_altivec_vsro((vector int)__a, (vector int)__b);
+static vector unsigned int __ATTRS_o_ai vec_vsro(vector unsigned int __a,
+ vector unsigned char __b) {
+ return (vector unsigned int)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_vsro(vector float __a, vector signed char __b)
-{
+static vector float __ATTRS_o_ai vec_vsro(vector float __a,
+ vector signed char __b) {
return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
-static vector float __ATTRS_o_ai
-vec_vsro(vector float __a, vector unsigned char __b)
-{
+static vector float __ATTRS_o_ai vec_vsro(vector float __a,
+ vector unsigned char __b) {
return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
/* vec_st */
-static void __ATTRS_o_ai
-vec_st(vector signed char __a, int __b, vector signed char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector signed char __a, int __b,
+ vector signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool char __a, int __b, vector bool char *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+ vector bool char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector short __a, int __b, vector short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector short __a, int __b, vector short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector short __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool short __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool short __a, int __b, vector bool short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool short __a, int __b,
+ vector bool short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_st(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector pixel __a, int __b, vector pixel *__c)
-{
+static void __ATTRS_o_ai vec_st(vector pixel __a, int __b, vector pixel *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector int __a, int __b, vector int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector int __a, int __b, vector int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector int __a, int __b, int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector bool int __a, int __b, vector bool int *__c)
-{
+static void __ATTRS_o_ai vec_st(vector bool int __a, int __b,
+ vector bool int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector float __a, int __b, vector float *__c)
-{
+static void __ATTRS_o_ai vec_st(vector float __a, int __b, vector float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_st(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_st(vector float __a, int __b, float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
/* vec_stvx */
-static void __ATTRS_o_ai
-vec_stvx(vector signed char __a, int __b, vector signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b,
+ vector signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool char __a, int __b, vector bool char *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+ vector bool char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector short __a, int __b, vector short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector short __a, int __b,
+ vector short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector short __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool short __a, int __b, vector bool short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b,
+ vector bool short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector pixel __a, int __b, vector pixel *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b,
+ vector pixel *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector int __a, int __b, vector int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector int __a, int __b, vector int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector int __a, int __b, int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector bool int __a, int __b, vector bool int *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b,
+ vector bool int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector float __a, int __b, vector float *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector float __a, int __b,
+ vector float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvx(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_stvx(vector float __a, int __b, float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
/* vec_ste */
-static void __ATTRS_o_ai
-vec_ste(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector short __a, int __b, short *__c) {
__builtin_altivec_stvehx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool short __a, int __b, short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector int __a, int __b, int *__c) {
__builtin_altivec_stvewx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_ste(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_ste(vector float __a, int __b, float *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
/* vec_stvebx */
-static void __ATTRS_o_ai
-vec_stvebx(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvebx(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvebx(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvebx(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvebx(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvebx(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
/* vec_stvehx */
-static void __ATTRS_o_ai
-vec_stvehx(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector short __a, int __b, short *__c) {
__builtin_altivec_stvehx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvehx(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvehx(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b,
+ short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvehx(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvehx(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvehx(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
/* vec_stvewx */
-static void __ATTRS_o_ai
-vec_stvewx(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvewx(vector int __a, int __b, int *__c) {
__builtin_altivec_stvewx(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvewx(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvewx(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvewx(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvewx(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvewx(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_stvewx(vector float __a, int __b, float *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
/* vec_stl */
-static void __ATTRS_o_ai
-vec_stl(vector signed char __a, int __b, vector signed char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector signed char __a, int __b,
+ vector signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool char __a, int __b, vector bool char *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool char __a, int __b,
+ vector bool char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector short __a, int __b, vector short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector short __a, int __b, vector short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector short __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool short __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool short __a, int __b, vector bool short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool short __a, int __b,
+ vector bool short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector pixel __a, int __b, vector pixel *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector pixel __a, int __b, vector pixel *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector int __a, int __b, vector int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector int __a, int __b, vector int *__c) {
__builtin_altivec_stvxl(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector int __a, int __b, int *__c) {
__builtin_altivec_stvxl(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector bool int __a, int __b, vector bool int *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector bool int __a, int __b,
+ vector bool int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector float __a, int __b, vector float *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector float __a, int __b, vector float *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stl(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_stl(vector float __a, int __b, float *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
/* vec_stvxl */
-static void __ATTRS_o_ai
-vec_stvxl(vector signed char __a, int __b, vector signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector signed char __a, int __b,
+ vector signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector signed char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector signed char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool char __a, int __b, signed char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b,
+ signed char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool char __a, int __b, unsigned char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b,
+ unsigned char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool char __a, int __b, vector bool char *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b,
+ vector bool char *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector short __a, int __b, vector short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector short __a, int __b,
+ vector short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector short __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool short __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool short __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool short __a, int __b, vector bool short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b,
+ vector bool short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector pixel __a, int __b, short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b, short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector pixel __a, int __b, unsigned short *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b,
+ unsigned short *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector pixel __a, int __b, vector pixel *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b,
+ vector pixel *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector int __a, int __b, vector int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector int __a, int __b, vector int *__c) {
__builtin_altivec_stvxl(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector int __a, int __b, int *__c) {
__builtin_altivec_stvxl(__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector unsigned int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector unsigned int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool int __a, int __b, int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b, int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool int __a, int __b, unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b,
+ unsigned int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector bool int __a, int __b, vector bool int *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b,
+ vector bool int *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector float __a, int __b, vector float *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector float __a, int __b,
+ vector float *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvxl(vector float __a, int __b, float *__c)
-{
+static void __ATTRS_o_ai vec_stvxl(vector float __a, int __b, float *__c) {
__builtin_altivec_stvxl((vector int)__a, __b, __c);
}
/* vec_sub */
-static vector signed char __ATTRS_o_ai
-vec_sub(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_sub(vector signed char __a,
+ vector signed char __b) {
return __a - __b;
}
-static vector signed char __ATTRS_o_ai
-vec_sub(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_sub(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a - __b;
}
-static vector signed char __ATTRS_o_ai
-vec_sub(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_sub(vector signed char __a,
+ vector bool char __b) {
return __a - (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_sub(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sub(vector unsigned char __a,
+ vector unsigned char __b) {
return __a - __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_sub(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sub(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a - __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_sub(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_sub(vector unsigned char __a,
+ vector bool char __b) {
return __a - (vector unsigned char)__b;
}
-static vector short __ATTRS_o_ai
-vec_sub(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_sub(vector short __a, vector short __b) {
return __a - __b;
}
-static vector short __ATTRS_o_ai
-vec_sub(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_sub(vector bool short __a,
+ vector short __b) {
return (vector short)__a - __b;
}
-static vector short __ATTRS_o_ai
-vec_sub(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_sub(vector short __a,
+ vector bool short __b) {
return __a - (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_sub(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sub(vector unsigned short __a,
+ vector unsigned short __b) {
return __a - __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_sub(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sub(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a - __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_sub(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_sub(vector unsigned short __a,
+ vector bool short __b) {
return __a - (vector unsigned short)__b;
}
-static vector int __ATTRS_o_ai
-vec_sub(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_sub(vector int __a, vector int __b) {
return __a - __b;
}
-static vector int __ATTRS_o_ai
-vec_sub(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_sub(vector bool int __a, vector int __b) {
return (vector int)__a - __b;
}
-static vector int __ATTRS_o_ai
-vec_sub(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_sub(vector int __a, vector bool int __b) {
return __a - (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_sub(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sub(vector unsigned int __a,
+ vector unsigned int __b) {
return __a - __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_sub(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sub(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a - __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_sub(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sub(vector unsigned int __a,
+ vector bool int __b) {
return __a - (vector unsigned int)__b;
}
-static vector float __ATTRS_o_ai
-vec_sub(vector float __a, vector float __b)
-{
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed __int128 __ATTRS_o_ai vec_sub(vector signed __int128 __a,
+ vector signed __int128 __b) {
+ return __a - __b;
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_sub(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __a - __b;
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
+static vector float __ATTRS_o_ai vec_sub(vector float __a, vector float __b) {
+ return __a - __b;
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai
+vec_sub(vector double __a, vector double __b) {
return __a - __b;
}
+#endif
/* vec_vsububm */
#define __builtin_altivec_vsububm vec_vsububm
-static vector signed char __ATTRS_o_ai
-vec_vsububm(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsububm(vector signed char __a,
+ vector signed char __b) {
return __a - __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vsububm(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsububm(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a - __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vsububm(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsububm(vector signed char __a,
+ vector bool char __b) {
return __a - (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsububm(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububm(vector unsigned char __a,
+ vector unsigned char __b) {
return __a - __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsububm(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububm(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a - __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsububm(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububm(vector unsigned char __a,
+ vector bool char __b) {
return __a - (vector unsigned char)__b;
}
@@ -8274,39 +9061,33 @@ vec_vsububm(vector unsigned char __a, vector bool char __b)
#define __builtin_altivec_vsubuhm vec_vsubuhm
-static vector short __ATTRS_o_ai
-vec_vsubuhm(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubuhm(vector short __a,
+ vector short __b) {
return __a - __b;
}
-static vector short __ATTRS_o_ai
-vec_vsubuhm(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubuhm(vector bool short __a,
+ vector short __b) {
return (vector short)__a - __b;
}
-static vector short __ATTRS_o_ai
-vec_vsubuhm(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubuhm(vector short __a,
+ vector bool short __b) {
return __a - (vector short)__b;
}
static vector unsigned short __ATTRS_o_ai
-vec_vsubuhm(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vsubuhm(vector unsigned short __a, vector unsigned short __b) {
return __a - __b;
}
static vector unsigned short __ATTRS_o_ai
-vec_vsubuhm(vector bool short __a, vector unsigned short __b)
-{
+vec_vsubuhm(vector bool short __a, vector unsigned short __b) {
return (vector unsigned short)__a - __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsubuhm(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsubuhm(vector unsigned short __a,
+ vector bool short __b) {
return __a - (vector unsigned short)__b;
}
@@ -8314,39 +9095,32 @@ vec_vsubuhm(vector unsigned short __a, vector bool short __b)
#define __builtin_altivec_vsubuwm vec_vsubuwm
-static vector int __ATTRS_o_ai
-vec_vsubuwm(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubuwm(vector int __a, vector int __b) {
return __a - __b;
}
-static vector int __ATTRS_o_ai
-vec_vsubuwm(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubuwm(vector bool int __a,
+ vector int __b) {
return (vector int)__a - __b;
}
-static vector int __ATTRS_o_ai
-vec_vsubuwm(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubuwm(vector int __a,
+ vector bool int __b) {
return __a - (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuwm(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector unsigned int __a,
+ vector unsigned int __b) {
return __a - __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuwm(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a - __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuwm(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector unsigned int __a,
+ vector bool int __b) {
return __a - (vector unsigned int)__b;
}
@@ -8355,298 +9129,314 @@ vec_vsubuwm(vector unsigned int __a, vector bool int __b)
#define __builtin_altivec_vsubfp vec_vsubfp
static vector float __attribute__((__always_inline__))
-vec_vsubfp(vector float __a, vector float __b)
-{
+vec_vsubfp(vector float __a, vector float __b) {
return __a - __b;
}
/* vec_subc */
-static vector unsigned int __attribute__((__always_inline__))
-vec_subc(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_subc(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsubcuw(__a, __b);
}
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector unsigned __int128 __ATTRS_o_ai
+vec_subc(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __builtin_altivec_vsubcuq(__a, __b);
+}
+
+static vector signed __int128 __ATTRS_o_ai
+vec_subc(vector signed __int128 __a, vector signed __int128 __b) {
+ return __builtin_altivec_vsubcuq(__a, __b);
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
/* vec_vsubcuw */
static vector unsigned int __attribute__((__always_inline__))
-vec_vsubcuw(vector unsigned int __a, vector unsigned int __b)
-{
+vec_vsubcuw(vector unsigned int __a, vector unsigned int __b) {
return __builtin_altivec_vsubcuw(__a, __b);
}
/* vec_subs */
-static vector signed char __ATTRS_o_ai
-vec_subs(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_subs(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vsubsbs(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_subs(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_subs(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vsubsbs((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_subs(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_subs(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vsubsbs(__a, (vector signed char)__b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_subs(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_subs(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vsububs(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_subs(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_subs(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vsububs((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_subs(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_subs(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vsububs(__a, (vector unsigned char)__b);
}
-static vector short __ATTRS_o_ai
-vec_subs(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_subs(vector short __a, vector short __b) {
return __builtin_altivec_vsubshs(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_subs(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_subs(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vsubshs((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_subs(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_subs(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vsubshs(__a, (vector short)__b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_subs(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_subs(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vsubuhs(__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_subs(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_subs(vector bool short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vsubuhs((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_subs(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_subs(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vsubuhs(__a, (vector unsigned short)__b);
}
-static vector int __ATTRS_o_ai
-vec_subs(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_subs(vector int __a, vector int __b) {
return __builtin_altivec_vsubsws(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_subs(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_subs(vector bool int __a, vector int __b) {
return __builtin_altivec_vsubsws((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_subs(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_subs(vector int __a, vector bool int __b) {
return __builtin_altivec_vsubsws(__a, (vector int)__b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_subs(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_subs(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsubuws(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_subs(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_subs(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsubuws((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_subs(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_subs(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vsubuws(__a, (vector unsigned int)__b);
}
/* vec_vsubsbs */
-static vector signed char __ATTRS_o_ai
-vec_vsubsbs(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsubsbs(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vsubsbs(__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsubsbs(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsubsbs(vector bool char __a,
+ vector signed char __b) {
return __builtin_altivec_vsubsbs((vector signed char)__a, __b);
}
-static vector signed char __ATTRS_o_ai
-vec_vsubsbs(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vsubsbs(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vsubsbs(__a, (vector signed char)__b);
}
/* vec_vsububs */
-static vector unsigned char __ATTRS_o_ai
-vec_vsububs(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububs(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vsububs(__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsububs(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububs(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vsububs((vector unsigned char)__a, __b);
}
-static vector unsigned char __ATTRS_o_ai
-vec_vsububs(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vsububs(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vsububs(__a, (vector unsigned char)__b);
}
/* vec_vsubshs */
-static vector short __ATTRS_o_ai
-vec_vsubshs(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubshs(vector short __a,
+ vector short __b) {
return __builtin_altivec_vsubshs(__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vsubshs(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubshs(vector bool short __a,
+ vector short __b) {
return __builtin_altivec_vsubshs((vector short)__a, __b);
}
-static vector short __ATTRS_o_ai
-vec_vsubshs(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vsubshs(vector short __a,
+ vector bool short __b) {
return __builtin_altivec_vsubshs(__a, (vector short)__b);
}
/* vec_vsubuhs */
static vector unsigned short __ATTRS_o_ai
-vec_vsubuhs(vector unsigned short __a, vector unsigned short __b)
-{
+vec_vsubuhs(vector unsigned short __a, vector unsigned short __b) {
return __builtin_altivec_vsubuhs(__a, __b);
}
static vector unsigned short __ATTRS_o_ai
-vec_vsubuhs(vector bool short __a, vector unsigned short __b)
-{
+vec_vsubuhs(vector bool short __a, vector unsigned short __b) {
return __builtin_altivec_vsubuhs((vector unsigned short)__a, __b);
}
-static vector unsigned short __ATTRS_o_ai
-vec_vsubuhs(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vsubuhs(vector unsigned short __a,
+ vector bool short __b) {
return __builtin_altivec_vsubuhs(__a, (vector unsigned short)__b);
}
/* vec_vsubsws */
-static vector int __ATTRS_o_ai
-vec_vsubsws(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubsws(vector int __a, vector int __b) {
return __builtin_altivec_vsubsws(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vsubsws(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubsws(vector bool int __a,
+ vector int __b) {
return __builtin_altivec_vsubsws((vector int)__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_vsubsws(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vsubsws(vector int __a,
+ vector bool int __b) {
return __builtin_altivec_vsubsws(__a, (vector int)__b);
}
/* vec_vsubuws */
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuws(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuws(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsubuws(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuws(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuws(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsubuws((vector unsigned int)__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_vsubuws(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vsubuws(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vsubuws(__a, (vector unsigned int)__b);
}
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+/* vec_vsubuqm */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vsubuqm(vector signed __int128 __a, vector signed __int128 __b) {
+ return __a - __b;
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vsubuqm(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __a - __b;
+}
+
+/* vec_vsubeuqm */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vsubeuqm(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vsubeuqm(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vsubeuqm(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vsubeuqm(__a, __b, __c);
+}
+
+/* vec_vsubcuq */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vsubcuq(vector signed __int128 __a, vector signed __int128 __b) {
+ return __builtin_altivec_vsubcuq(__a, __b);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vsubcuq(vector unsigned __int128 __a, vector unsigned __int128 __b) {
+ return __builtin_altivec_vsubcuq(__a, __b);
+}
+
+/* vec_vsubecuq */
+
+static vector signed __int128 __ATTRS_o_ai
+vec_vsubecuq(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vsubecuq(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_vsubecuq(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vsubecuq(__a, __b, __c);
+}
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+
/* vec_sum4s */
-static vector int __ATTRS_o_ai
-vec_sum4s(vector signed char __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_sum4s(vector signed char __a,
+ vector int __b) {
return __builtin_altivec_vsum4sbs(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai
-vec_sum4s(vector unsigned char __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_sum4s(vector unsigned char __a,
+ vector unsigned int __b) {
return __builtin_altivec_vsum4ubs(__a, __b);
}
-static vector int __ATTRS_o_ai
-vec_sum4s(vector signed short __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_sum4s(vector signed short __a,
+ vector int __b) {
return __builtin_altivec_vsum4shs(__a, __b);
}
/* vec_vsum4sbs */
static vector int __attribute__((__always_inline__))
-vec_vsum4sbs(vector signed char __a, vector int __b)
-{
+vec_vsum4sbs(vector signed char __a, vector int __b) {
return __builtin_altivec_vsum4sbs(__a, __b);
}
/* vec_vsum4ubs */
static vector unsigned int __attribute__((__always_inline__))
-vec_vsum4ubs(vector unsigned char __a, vector unsigned int __b)
-{
+vec_vsum4ubs(vector unsigned char __a, vector unsigned int __b) {
return __builtin_altivec_vsum4ubs(__a, __b);
}
/* vec_vsum4shs */
static vector int __attribute__((__always_inline__))
-vec_vsum4shs(vector signed short __a, vector int __b)
-{
+vec_vsum4shs(vector signed short __a, vector int __b) {
return __builtin_altivec_vsum4shs(__a, __b);
}
@@ -8659,16 +9449,15 @@ vec_vsum4shs(vector signed short __a, vector int __b)
endian we must perform some permutes. */
static vector signed int __attribute__((__always_inline__))
-vec_sum2s(vector int __a, vector int __b)
-{
+vec_sum2s(vector int __a, vector int __b) {
#ifdef __LITTLE_ENDIAN__
- vector int __c = (vector signed int)
- vec_perm(__b, __b, (vector unsigned char)
- (4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11));
+ vector int __c = (vector signed int)vec_perm(
+ __b, __b, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15,
+ 8, 9, 10, 11));
__c = __builtin_altivec_vsum2sws(__a, __c);
- return (vector signed int)
- vec_perm(__c, __c, (vector unsigned char)
- (4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11));
+ return (vector signed int)vec_perm(
+ __c, __c, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15,
+ 8, 9, 10, 11));
#else
return __builtin_altivec_vsum2sws(__a, __b);
#endif
@@ -8677,16 +9466,15 @@ vec_sum2s(vector int __a, vector int __b)
/* vec_vsum2sws */
static vector signed int __attribute__((__always_inline__))
-vec_vsum2sws(vector int __a, vector int __b)
-{
+vec_vsum2sws(vector int __a, vector int __b) {
#ifdef __LITTLE_ENDIAN__
- vector int __c = (vector signed int)
- vec_perm(__b, __b, (vector unsigned char)
- (4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11));
+ vector int __c = (vector signed int)vec_perm(
+ __b, __b, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15,
+ 8, 9, 10, 11));
__c = __builtin_altivec_vsum2sws(__a, __c);
- return (vector signed int)
- vec_perm(__c, __c, (vector unsigned char)
- (4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11));
+ return (vector signed int)vec_perm(
+ __c, __c, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15,
+ 8, 9, 10, 11));
#else
return __builtin_altivec_vsum2sws(__a, __b);
#endif
@@ -8701,8 +9489,7 @@ vec_vsum2sws(vector int __a, vector int __b)
some permutes. */
static vector signed int __attribute__((__always_inline__))
-vec_sums(vector signed int __a, vector signed int __b)
-{
+vec_sums(vector signed int __a, vector signed int __b) {
#ifdef __LITTLE_ENDIAN__
__b = (vector signed int)vec_splat(__b, 3);
__b = __builtin_altivec_vsumsws(__a, __b);
@@ -8715,8 +9502,7 @@ vec_sums(vector signed int __a, vector signed int __b)
/* vec_vsumsws */
static vector signed int __attribute__((__always_inline__))
-vec_vsumsws(vector signed int __a, vector signed int __b)
-{
+vec_vsumsws(vector signed int __a, vector signed int __b) {
#ifdef __LITTLE_ENDIAN__
__b = (vector signed int)vec_splat(__b, 3);
__b = __builtin_altivec_vsumsws(__a, __b);
@@ -8728,17 +9514,25 @@ vec_vsumsws(vector signed int __a, vector signed int __b)
/* vec_trunc */
-static vector float __attribute__((__always_inline__))
-vec_trunc(vector float __a)
-{
+static vector float __ATTRS_o_ai
+vec_trunc(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvrspiz(__a);
+#else
return __builtin_altivec_vrfiz(__a);
+#endif
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_trunc(vector double __a) {
+ return __builtin_vsx_xvrdpiz(__a);
+}
+#endif
+
/* vec_vrfiz */
static vector float __attribute__((__always_inline__))
-vec_vrfiz(vector float __a)
-{
+vec_vrfiz(vector float __a) {
return __builtin_altivec_vrfiz(__a);
}
@@ -8747,9 +9541,7 @@ vec_vrfiz(vector float __a)
/* The vector unpack instructions all have a big-endian bias, so for
little endian we must reverse the meanings of "high" and "low." */
-static vector short __ATTRS_o_ai
-vec_unpackh(vector signed char __a)
-{
+static vector short __ATTRS_o_ai vec_unpackh(vector signed char __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupklsb((vector char)__a);
#else
@@ -8757,9 +9549,7 @@ vec_unpackh(vector signed char __a)
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_unpackh(vector bool char __a)
-{
+static vector bool short __ATTRS_o_ai vec_unpackh(vector bool char __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool short)__builtin_altivec_vupklsb((vector char)__a);
#else
@@ -8767,9 +9557,7 @@ vec_unpackh(vector bool char __a)
#endif
}
-static vector int __ATTRS_o_ai
-vec_unpackh(vector short __a)
-{
+static vector int __ATTRS_o_ai vec_unpackh(vector short __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupklsh(__a);
#else
@@ -8777,9 +9565,7 @@ vec_unpackh(vector short __a)
#endif
}
-static vector bool int __ATTRS_o_ai
-vec_unpackh(vector bool short __a)
-{
+static vector bool int __ATTRS_o_ai vec_unpackh(vector bool short __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool int)__builtin_altivec_vupklsh((vector short)__a);
#else
@@ -8787,9 +9573,7 @@ vec_unpackh(vector bool short __a)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_unpackh(vector pixel __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_unpackh(vector pixel __a) {
#ifdef __LITTLE_ENDIAN__
return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a);
#else
@@ -8797,11 +9581,27 @@ vec_unpackh(vector pixel __a)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector long long __ATTRS_o_ai vec_unpackh(vector int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vupklsw(__a);
+#else
+ return __builtin_altivec_vupkhsw(__a);
+#endif
+}
+
+static vector bool long long __ATTRS_o_ai vec_unpackh(vector bool int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a);
+#else
+ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a);
+#endif
+}
+#endif
+
/* vec_vupkhsb */
-static vector short __ATTRS_o_ai
-vec_vupkhsb(vector signed char __a)
-{
+static vector short __ATTRS_o_ai vec_vupkhsb(vector signed char __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupklsb((vector char)__a);
#else
@@ -8809,9 +9609,7 @@ vec_vupkhsb(vector signed char __a)
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_vupkhsb(vector bool char __a)
-{
+static vector bool short __ATTRS_o_ai vec_vupkhsb(vector bool char __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool short)__builtin_altivec_vupklsb((vector char)__a);
#else
@@ -8821,9 +9619,7 @@ vec_vupkhsb(vector bool char __a)
/* vec_vupkhsh */
-static vector int __ATTRS_o_ai
-vec_vupkhsh(vector short __a)
-{
+static vector int __ATTRS_o_ai vec_vupkhsh(vector short __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupklsh(__a);
#else
@@ -8831,9 +9627,7 @@ vec_vupkhsh(vector short __a)
#endif
}
-static vector bool int __ATTRS_o_ai
-vec_vupkhsh(vector bool short __a)
-{
+static vector bool int __ATTRS_o_ai vec_vupkhsh(vector bool short __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool int)__builtin_altivec_vupklsh((vector short)__a);
#else
@@ -8841,9 +9635,7 @@ vec_vupkhsh(vector bool short __a)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_vupkhsh(vector pixel __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_vupkhsh(vector pixel __a) {
#ifdef __LITTLE_ENDIAN__
return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a);
#else
@@ -8851,11 +9643,29 @@ vec_vupkhsh(vector pixel __a)
#endif
}
+/* vec_vupkhsw */
+
+#ifdef __POWER8_VECTOR__
+static vector long long __ATTRS_o_ai vec_vupkhsw(vector int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vupklsw(__a);
+#else
+ return __builtin_altivec_vupkhsw(__a);
+#endif
+}
+
+static vector bool long long __ATTRS_o_ai vec_vupkhsw(vector bool int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a);
+#else
+ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a);
+#endif
+}
+#endif
+
/* vec_unpackl */
-static vector short __ATTRS_o_ai
-vec_unpackl(vector signed char __a)
-{
+static vector short __ATTRS_o_ai vec_unpackl(vector signed char __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupkhsb((vector char)__a);
#else
@@ -8863,9 +9673,7 @@ vec_unpackl(vector signed char __a)
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_unpackl(vector bool char __a)
-{
+static vector bool short __ATTRS_o_ai vec_unpackl(vector bool char __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a);
#else
@@ -8873,9 +9681,7 @@ vec_unpackl(vector bool char __a)
#endif
}
-static vector int __ATTRS_o_ai
-vec_unpackl(vector short __a)
-{
+static vector int __ATTRS_o_ai vec_unpackl(vector short __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupkhsh(__a);
#else
@@ -8883,9 +9689,7 @@ vec_unpackl(vector short __a)
#endif
}
-static vector bool int __ATTRS_o_ai
-vec_unpackl(vector bool short __a)
-{
+static vector bool int __ATTRS_o_ai vec_unpackl(vector bool short __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a);
#else
@@ -8893,9 +9697,7 @@ vec_unpackl(vector bool short __a)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_unpackl(vector pixel __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_unpackl(vector pixel __a) {
#ifdef __LITTLE_ENDIAN__
return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a);
#else
@@ -8903,11 +9705,27 @@ vec_unpackl(vector pixel __a)
#endif
}
+#ifdef __POWER8_VECTOR__
+static vector long long __ATTRS_o_ai vec_unpackl(vector int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vupkhsw(__a);
+#else
+ return __builtin_altivec_vupklsw(__a);
+#endif
+}
+
+static vector bool long long __ATTRS_o_ai vec_unpackl(vector bool int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a);
+#else
+ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a);
+#endif
+}
+#endif
+
/* vec_vupklsb */
-static vector short __ATTRS_o_ai
-vec_vupklsb(vector signed char __a)
-{
+static vector short __ATTRS_o_ai vec_vupklsb(vector signed char __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupkhsb((vector char)__a);
#else
@@ -8915,9 +9733,7 @@ vec_vupklsb(vector signed char __a)
#endif
}
-static vector bool short __ATTRS_o_ai
-vec_vupklsb(vector bool char __a)
-{
+static vector bool short __ATTRS_o_ai vec_vupklsb(vector bool char __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a);
#else
@@ -8927,9 +9743,7 @@ vec_vupklsb(vector bool char __a)
/* vec_vupklsh */
-static vector int __ATTRS_o_ai
-vec_vupklsh(vector short __a)
-{
+static vector int __ATTRS_o_ai vec_vupklsh(vector short __a) {
#ifdef __LITTLE_ENDIAN__
return __builtin_altivec_vupkhsh(__a);
#else
@@ -8937,9 +9751,7 @@ vec_vupklsh(vector short __a)
#endif
}
-static vector bool int __ATTRS_o_ai
-vec_vupklsh(vector bool short __a)
-{
+static vector bool int __ATTRS_o_ai vec_vupklsh(vector bool short __a) {
#ifdef __LITTLE_ENDIAN__
return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a);
#else
@@ -8947,9 +9759,7 @@ vec_vupklsh(vector bool short __a)
#endif
}
-static vector unsigned int __ATTRS_o_ai
-vec_vupklsh(vector pixel __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_vupklsh(vector pixel __a) {
#ifdef __LITTLE_ENDIAN__
return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a);
#else
@@ -8957,43 +9767,56 @@ vec_vupklsh(vector pixel __a)
#endif
}
+/* vec_vupklsw */
+
+#ifdef __POWER8_VECTOR__
+static vector long long __ATTRS_o_ai vec_vupklsw(vector int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vupkhsw(__a);
+#else
+ return __builtin_altivec_vupklsw(__a);
+#endif
+}
+
+static vector bool long long __ATTRS_o_ai vec_vupklsw(vector bool int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a);
+#else
+ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a);
+#endif
+}
+#endif
+
/* vec_vsx_ld */
#ifdef __VSX__
-static vector signed int __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector signed int *__b)
-{
+static vector signed int __ATTRS_o_ai vec_vsx_ld(int __a,
+ const vector signed int *__b) {
return (vector signed int)__builtin_vsx_lxvw4x(__a, __b);
}
static vector unsigned int __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector unsigned int *__b)
-{
+vec_vsx_ld(int __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_vsx_lxvw4x(__a, __b);
}
-static vector float __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector float *__b)
-{
+static vector float __ATTRS_o_ai vec_vsx_ld(int __a, const vector float *__b) {
return (vector float)__builtin_vsx_lxvw4x(__a, __b);
}
static vector signed long long __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector signed long long *__b)
-{
+vec_vsx_ld(int __a, const vector signed long long *__b) {
return (vector signed long long)__builtin_vsx_lxvd2x(__a, __b);
}
static vector unsigned long long __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector unsigned long long *__b)
-{
+vec_vsx_ld(int __a, const vector unsigned long long *__b) {
return (vector unsigned long long)__builtin_vsx_lxvd2x(__a, __b);
}
-static vector double __ATTRS_o_ai
-vec_vsx_ld(int __a, const vector double *__b)
-{
+static vector double __ATTRS_o_ai vec_vsx_ld(int __a,
+ const vector double *__b) {
return (vector double)__builtin_vsx_lxvd2x(__a, __b);
}
@@ -9003,40 +9826,33 @@ vec_vsx_ld(int __a, const vector double *__b)
#ifdef __VSX__
-static void __ATTRS_o_ai
-vec_vsx_st(vector signed int __a, int __b, vector signed int *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector signed int __a, int __b,
+ vector signed int *__c) {
__builtin_vsx_stxvw4x((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_vsx_st(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
__builtin_vsx_stxvw4x((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_vsx_st(vector float __a, int __b, vector float *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector float __a, int __b,
+ vector float *__c) {
__builtin_vsx_stxvw4x((vector int)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_vsx_st(vector signed long long __a, int __b, vector signed long long *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector signed long long __a, int __b,
+ vector signed long long *__c) {
__builtin_vsx_stxvd2x((vector double)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_vsx_st(vector unsigned long long __a, int __b,
- vector unsigned long long *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector unsigned long long __a, int __b,
+ vector unsigned long long *__c) {
__builtin_vsx_stxvd2x((vector double)__a, __b, __c);
}
-static void __ATTRS_o_ai
-vec_vsx_st(vector double __a, int __b, vector double *__c)
-{
+static void __ATTRS_o_ai vec_vsx_st(vector double __a, int __b,
+ vector double *__c) {
__builtin_vsx_stxvd2x((vector double)__a, __b, __c);
}
@@ -9046,1656 +9862,1312 @@ vec_vsx_st(vector double __a, int __b, vector double *__c)
#define __builtin_altivec_vxor vec_xor
-static vector signed char __ATTRS_o_ai
-vec_xor(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_xor(vector signed char __a,
+ vector signed char __b) {
return __a ^ __b;
}
-static vector signed char __ATTRS_o_ai
-vec_xor(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_xor(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a ^ __b;
}
-static vector signed char __ATTRS_o_ai
-vec_xor(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_xor(vector signed char __a,
+ vector bool char __b) {
return __a ^ (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_xor(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a,
+ vector unsigned char __b) {
return __a ^ __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_xor(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_xor(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a ^ __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_xor(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a,
+ vector bool char __b) {
return __a ^ (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_xor(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_xor(vector bool char __a,
+ vector bool char __b) {
return __a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_xor(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_xor(vector short __a, vector short __b) {
return __a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_xor(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_xor(vector bool short __a,
+ vector short __b) {
return (vector short)__a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_xor(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_xor(vector short __a,
+ vector bool short __b) {
return __a ^ (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_xor(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_xor(vector unsigned short __a,
+ vector unsigned short __b) {
return __a ^ __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_xor(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_xor(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a ^ __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_xor(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_xor(vector unsigned short __a,
+ vector bool short __b) {
return __a ^ (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_xor(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_xor(vector bool short __a,
+ vector bool short __b) {
return __a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_xor(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_xor(vector int __a, vector int __b) {
return __a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_xor(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_xor(vector bool int __a, vector int __b) {
return (vector int)__a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_xor(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_xor(vector int __a, vector bool int __b) {
return __a ^ (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_xor(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_xor(vector unsigned int __a,
+ vector unsigned int __b) {
return __a ^ __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_xor(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_xor(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a ^ __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_xor(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_xor(vector unsigned int __a,
+ vector bool int __b) {
return __a ^ (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_xor(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_xor(vector bool int __a,
+ vector bool int __b) {
return __a ^ __b;
}
-static vector float __ATTRS_o_ai
-vec_xor(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_xor(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_xor(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_xor(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_xor(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_xor(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_xor(vector signed long long __a, vector signed long long __b) {
+ return __a ^ __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_xor(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a ^ __b;
+}
+
+static vector signed long long __ATTRS_o_ai vec_xor(vector signed long long __a,
+ vector bool long long __b) {
+ return __a ^ (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_xor(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a ^ __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_xor(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a ^ __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_xor(vector unsigned long long __a, vector bool long long __b) {
+ return __a ^ (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_xor(vector bool long long __a,
+ vector bool long long __b) {
+ return __a ^ __b;
+}
+
+static vector double __ATTRS_o_ai
+vec_xor(vector double __a, vector double __b) {
+ return (vector double)((vector unsigned long long)__a ^
+ (vector unsigned long long)__b);
+}
+
+static vector double __ATTRS_o_ai
+vec_xor(vector double __a, vector bool long long __b) {
+ return (vector double)((vector unsigned long long)__a ^
+ (vector unsigned long long) __b);
+}
+
+static vector double __ATTRS_o_ai
+vec_xor(vector bool long long __a, vector double __b) {
+ return (vector double)((vector unsigned long long)__a ^
+ (vector unsigned long long)__b);
+}
+#endif
+
/* vec_vxor */
-static vector signed char __ATTRS_o_ai
-vec_vxor(vector signed char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vxor(vector signed char __a,
+ vector signed char __b) {
return __a ^ __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vxor(vector bool char __a, vector signed char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vxor(vector bool char __a,
+ vector signed char __b) {
return (vector signed char)__a ^ __b;
}
-static vector signed char __ATTRS_o_ai
-vec_vxor(vector signed char __a, vector bool char __b)
-{
+static vector signed char __ATTRS_o_ai vec_vxor(vector signed char __a,
+ vector bool char __b) {
return __a ^ (vector signed char)__b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vxor(vector unsigned char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vxor(vector unsigned char __a,
+ vector unsigned char __b) {
return __a ^ __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vxor(vector bool char __a, vector unsigned char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vxor(vector bool char __a,
+ vector unsigned char __b) {
return (vector unsigned char)__a ^ __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_vxor(vector unsigned char __a, vector bool char __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_vxor(vector unsigned char __a,
+ vector bool char __b) {
return __a ^ (vector unsigned char)__b;
}
-static vector bool char __ATTRS_o_ai
-vec_vxor(vector bool char __a, vector bool char __b)
-{
+static vector bool char __ATTRS_o_ai vec_vxor(vector bool char __a,
+ vector bool char __b) {
return __a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_vxor(vector short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vxor(vector short __a, vector short __b) {
return __a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_vxor(vector bool short __a, vector short __b)
-{
+static vector short __ATTRS_o_ai vec_vxor(vector bool short __a,
+ vector short __b) {
return (vector short)__a ^ __b;
}
-static vector short __ATTRS_o_ai
-vec_vxor(vector short __a, vector bool short __b)
-{
+static vector short __ATTRS_o_ai vec_vxor(vector short __a,
+ vector bool short __b) {
return __a ^ (vector short)__b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vxor(vector unsigned short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vxor(vector unsigned short __a,
+ vector unsigned short __b) {
return __a ^ __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vxor(vector bool short __a, vector unsigned short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vxor(vector bool short __a,
+ vector unsigned short __b) {
return (vector unsigned short)__a ^ __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_vxor(vector unsigned short __a, vector bool short __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_vxor(vector unsigned short __a,
+ vector bool short __b) {
return __a ^ (vector unsigned short)__b;
}
-static vector bool short __ATTRS_o_ai
-vec_vxor(vector bool short __a, vector bool short __b)
-{
+static vector bool short __ATTRS_o_ai vec_vxor(vector bool short __a,
+ vector bool short __b) {
return __a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_vxor(vector int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vxor(vector int __a, vector int __b) {
return __a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_vxor(vector bool int __a, vector int __b)
-{
+static vector int __ATTRS_o_ai vec_vxor(vector bool int __a, vector int __b) {
return (vector int)__a ^ __b;
}
-static vector int __ATTRS_o_ai
-vec_vxor(vector int __a, vector bool int __b)
-{
+static vector int __ATTRS_o_ai vec_vxor(vector int __a, vector bool int __b) {
return __a ^ (vector int)__b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vxor(vector unsigned int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vxor(vector unsigned int __a,
+ vector unsigned int __b) {
return __a ^ __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vxor(vector bool int __a, vector unsigned int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vxor(vector bool int __a,
+ vector unsigned int __b) {
return (vector unsigned int)__a ^ __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_vxor(vector unsigned int __a, vector bool int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_vxor(vector unsigned int __a,
+ vector bool int __b) {
return __a ^ (vector unsigned int)__b;
}
-static vector bool int __ATTRS_o_ai
-vec_vxor(vector bool int __a, vector bool int __b)
-{
+static vector bool int __ATTRS_o_ai vec_vxor(vector bool int __a,
+ vector bool int __b) {
return __a ^ __b;
}
-static vector float __ATTRS_o_ai
-vec_vxor(vector float __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vxor(vector float __a, vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vxor(vector bool int __a, vector float __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vxor(vector bool int __a,
+ vector float __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
-static vector float __ATTRS_o_ai
-vec_vxor(vector float __a, vector bool int __b)
-{
- vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b;
+static vector float __ATTRS_o_ai vec_vxor(vector float __a,
+ vector bool int __b) {
+ vector unsigned int __res =
+ (vector unsigned int)__a ^ (vector unsigned int)__b;
return (vector float)__res;
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_vxor(vector signed long long __a, vector signed long long __b) {
+ return __a ^ __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vxor(vector bool long long __a, vector signed long long __b) {
+ return (vector signed long long)__a ^ __b;
+}
+
+static vector signed long long __ATTRS_o_ai
+vec_vxor(vector signed long long __a, vector bool long long __b) {
+ return __a ^ (vector signed long long)__b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vxor(vector unsigned long long __a, vector unsigned long long __b) {
+ return __a ^ __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vxor(vector bool long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)__a ^ __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_vxor(vector unsigned long long __a, vector bool long long __b) {
+ return __a ^ (vector unsigned long long)__b;
+}
+
+static vector bool long long __ATTRS_o_ai vec_vxor(vector bool long long __a,
+ vector bool long long __b) {
+ return __a ^ __b;
+}
+#endif
+
/* ------------------------ extensions for CBEA ----------------------------- */
/* vec_extract */
-static signed char __ATTRS_o_ai
-vec_extract(vector signed char __a, int __b)
-{
+static signed char __ATTRS_o_ai vec_extract(vector signed char __a, int __b) {
return __a[__b];
}
-static unsigned char __ATTRS_o_ai
-vec_extract(vector unsigned char __a, int __b)
-{
+static unsigned char __ATTRS_o_ai vec_extract(vector unsigned char __a,
+ int __b) {
return __a[__b];
}
-static short __ATTRS_o_ai
-vec_extract(vector short __a, int __b)
-{
+static short __ATTRS_o_ai vec_extract(vector short __a, int __b) {
return __a[__b];
}
-static unsigned short __ATTRS_o_ai
-vec_extract(vector unsigned short __a, int __b)
-{
+static unsigned short __ATTRS_o_ai vec_extract(vector unsigned short __a,
+ int __b) {
return __a[__b];
}
-static int __ATTRS_o_ai
-vec_extract(vector int __a, int __b)
-{
+static int __ATTRS_o_ai vec_extract(vector int __a, int __b) {
return __a[__b];
}
-static unsigned int __ATTRS_o_ai
-vec_extract(vector unsigned int __a, int __b)
-{
+static unsigned int __ATTRS_o_ai vec_extract(vector unsigned int __a, int __b) {
return __a[__b];
}
-static float __ATTRS_o_ai
-vec_extract(vector float __a, int __b)
-{
+static float __ATTRS_o_ai vec_extract(vector float __a, int __b) {
return __a[__b];
}
/* vec_insert */
-static vector signed char __ATTRS_o_ai
-vec_insert(signed char __a, vector signed char __b, int __c)
-{
+static vector signed char __ATTRS_o_ai vec_insert(signed char __a,
+ vector signed char __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
-static vector unsigned char __ATTRS_o_ai
-vec_insert(unsigned char __a, vector unsigned char __b, int __c)
-{
+static vector unsigned char __ATTRS_o_ai vec_insert(unsigned char __a,
+ vector unsigned char __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
-static vector short __ATTRS_o_ai
-vec_insert(short __a, vector short __b, int __c)
-{
+static vector short __ATTRS_o_ai vec_insert(short __a, vector short __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
-static vector unsigned short __ATTRS_o_ai
-vec_insert(unsigned short __a, vector unsigned short __b, int __c)
-{
+static vector unsigned short __ATTRS_o_ai vec_insert(unsigned short __a,
+ vector unsigned short __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
-static vector int __ATTRS_o_ai
-vec_insert(int __a, vector int __b, int __c)
-{
+static vector int __ATTRS_o_ai vec_insert(int __a, vector int __b, int __c) {
__b[__c] = __a;
return __b;
}
-static vector unsigned int __ATTRS_o_ai
-vec_insert(unsigned int __a, vector unsigned int __b, int __c)
-{
+static vector unsigned int __ATTRS_o_ai vec_insert(unsigned int __a,
+ vector unsigned int __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
-static vector float __ATTRS_o_ai
-vec_insert(float __a, vector float __b, int __c)
-{
+static vector float __ATTRS_o_ai vec_insert(float __a, vector float __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
/* vec_lvlx */
-static vector signed char __ATTRS_o_ai
-vec_lvlx(int __a, const signed char *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector signed char)(0),
+static vector signed char __ATTRS_o_ai vec_lvlx(int __a,
+ const signed char *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector signed char)(0),
vec_lvsl(__a, __b));
}
-static vector signed char __ATTRS_o_ai
-vec_lvlx(int __a, const vector signed char *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector signed char)(0),
+static vector signed char __ATTRS_o_ai vec_lvlx(int __a,
+ const vector signed char *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector signed char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvlx(int __a, const unsigned char *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned char)(0),
+static vector unsigned char __ATTRS_o_ai vec_lvlx(int __a,
+ const unsigned char *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned char)(0),
vec_lvsl(__a, __b));
}
static vector unsigned char __ATTRS_o_ai
-vec_lvlx(int __a, const vector unsigned char *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned char)(0),
+vec_lvlx(int __a, const vector unsigned char *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool char __ATTRS_o_ai
-vec_lvlx(int __a, const vector bool char *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector bool char)(0),
+static vector bool char __ATTRS_o_ai vec_lvlx(int __a,
+ const vector bool char *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector bool char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector short __ATTRS_o_ai
-vec_lvlx(int __a, const short *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector short)(0),
- vec_lvsl(__a, __b));
+static vector short __ATTRS_o_ai vec_lvlx(int __a, const short *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector short)(0), vec_lvsl(__a, __b));
}
-static vector short __ATTRS_o_ai
-vec_lvlx(int __a, const vector short *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector short)(0),
+static vector short __ATTRS_o_ai vec_lvlx(int __a, const vector short *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvlx(int __a, const unsigned short *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned short)(0),
+static vector unsigned short __ATTRS_o_ai vec_lvlx(int __a,
+ const unsigned short *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned short)(0),
vec_lvsl(__a, __b));
}
static vector unsigned short __ATTRS_o_ai
-vec_lvlx(int __a, const vector unsigned short *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned short)(0),
+vec_lvlx(int __a, const vector unsigned short *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool short __ATTRS_o_ai
-vec_lvlx(int __a, const vector bool short *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector bool short)(0),
+static vector bool short __ATTRS_o_ai vec_lvlx(int __a,
+ const vector bool short *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector bool short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector pixel __ATTRS_o_ai
-vec_lvlx(int __a, const vector pixel *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector pixel)(0),
+static vector pixel __ATTRS_o_ai vec_lvlx(int __a, const vector pixel *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector pixel)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector int __ATTRS_o_ai
-vec_lvlx(int __a, const int *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector int)(0),
- vec_lvsl(__a, __b));
+static vector int __ATTRS_o_ai vec_lvlx(int __a, const int *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector int)(0), vec_lvsl(__a, __b));
}
-static vector int __ATTRS_o_ai
-vec_lvlx(int __a, const vector int *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector int)(0),
+static vector int __ATTRS_o_ai vec_lvlx(int __a, const vector int *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvlx(int __a, const unsigned int *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned int)(0),
+static vector unsigned int __ATTRS_o_ai vec_lvlx(int __a,
+ const unsigned int *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned int)(0),
vec_lvsl(__a, __b));
}
static vector unsigned int __ATTRS_o_ai
-vec_lvlx(int __a, const vector unsigned int *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector unsigned int)(0),
+vec_lvlx(int __a, const vector unsigned int *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector unsigned int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool int __ATTRS_o_ai
-vec_lvlx(int __a, const vector bool int *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector bool int)(0),
+static vector bool int __ATTRS_o_ai vec_lvlx(int __a,
+ const vector bool int *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector bool int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector float __ATTRS_o_ai
-vec_lvlx(int __a, const float *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector float)(0),
- vec_lvsl(__a, __b));
+static vector float __ATTRS_o_ai vec_lvlx(int __a, const float *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector float)(0), vec_lvsl(__a, __b));
}
-static vector float __ATTRS_o_ai
-vec_lvlx(int __a, const vector float *__b)
-{
- return vec_perm(vec_ld(__a, __b),
- (vector float)(0),
+static vector float __ATTRS_o_ai vec_lvlx(int __a, const vector float *__b) {
+ return vec_perm(vec_ld(__a, __b), (vector float)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
/* vec_lvlxl */
-static vector signed char __ATTRS_o_ai
-vec_lvlxl(int __a, const signed char *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector signed char)(0),
+static vector signed char __ATTRS_o_ai vec_lvlxl(int __a,
+ const signed char *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector signed char)(0),
vec_lvsl(__a, __b));
}
static vector signed char __ATTRS_o_ai
-vec_lvlxl(int __a, const vector signed char *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector signed char)(0),
+vec_lvlxl(int __a, const vector signed char *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector signed char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvlxl(int __a, const unsigned char *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned char)(0),
+static vector unsigned char __ATTRS_o_ai vec_lvlxl(int __a,
+ const unsigned char *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned char)(0),
vec_lvsl(__a, __b));
}
static vector unsigned char __ATTRS_o_ai
-vec_lvlxl(int __a, const vector unsigned char *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned char)(0),
+vec_lvlxl(int __a, const vector unsigned char *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool char __ATTRS_o_ai
-vec_lvlxl(int __a, const vector bool char *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector bool char)(0),
+static vector bool char __ATTRS_o_ai vec_lvlxl(int __a,
+ const vector bool char *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector bool char)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector short __ATTRS_o_ai
-vec_lvlxl(int __a, const short *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector short)(0),
- vec_lvsl(__a, __b));
+static vector short __ATTRS_o_ai vec_lvlxl(int __a, const short *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector short)(0), vec_lvsl(__a, __b));
}
-static vector short __ATTRS_o_ai
-vec_lvlxl(int __a, const vector short *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector short)(0),
+static vector short __ATTRS_o_ai vec_lvlxl(int __a, const vector short *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvlxl(int __a, const unsigned short *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned short)(0),
+static vector unsigned short __ATTRS_o_ai vec_lvlxl(int __a,
+ const unsigned short *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned short)(0),
vec_lvsl(__a, __b));
}
static vector unsigned short __ATTRS_o_ai
-vec_lvlxl(int __a, const vector unsigned short *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned short)(0),
+vec_lvlxl(int __a, const vector unsigned short *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool short __ATTRS_o_ai
-vec_lvlxl(int __a, const vector bool short *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector bool short)(0),
+static vector bool short __ATTRS_o_ai vec_lvlxl(int __a,
+ const vector bool short *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector bool short)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector pixel __ATTRS_o_ai
-vec_lvlxl(int __a, const vector pixel *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector pixel)(0),
+static vector pixel __ATTRS_o_ai vec_lvlxl(int __a, const vector pixel *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector pixel)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector int __ATTRS_o_ai
-vec_lvlxl(int __a, const int *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector int)(0),
- vec_lvsl(__a, __b));
+static vector int __ATTRS_o_ai vec_lvlxl(int __a, const int *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector int)(0), vec_lvsl(__a, __b));
}
-static vector int __ATTRS_o_ai
-vec_lvlxl(int __a, const vector int *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector int)(0),
+static vector int __ATTRS_o_ai vec_lvlxl(int __a, const vector int *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvlxl(int __a, const unsigned int *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned int)(0),
+static vector unsigned int __ATTRS_o_ai vec_lvlxl(int __a,
+ const unsigned int *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned int)(0),
vec_lvsl(__a, __b));
}
static vector unsigned int __ATTRS_o_ai
-vec_lvlxl(int __a, const vector unsigned int *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector unsigned int)(0),
+vec_lvlxl(int __a, const vector unsigned int *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector unsigned int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool int __ATTRS_o_ai
-vec_lvlxl(int __a, const vector bool int *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector bool int)(0),
+static vector bool int __ATTRS_o_ai vec_lvlxl(int __a,
+ const vector bool int *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector bool int)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector float __ATTRS_o_ai
-vec_lvlxl(int __a, const float *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector float)(0),
- vec_lvsl(__a, __b));
+static vector float __ATTRS_o_ai vec_lvlxl(int __a, const float *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector float)(0), vec_lvsl(__a, __b));
}
-static vector float __ATTRS_o_ai
-vec_lvlxl(int __a, vector float *__b)
-{
- return vec_perm(vec_ldl(__a, __b),
- (vector float)(0),
+static vector float __ATTRS_o_ai vec_lvlxl(int __a, vector float *__b) {
+ return vec_perm(vec_ldl(__a, __b), (vector float)(0),
vec_lvsl(__a, (unsigned char *)__b));
}
/* vec_lvrx */
-static vector signed char __ATTRS_o_ai
-vec_lvrx(int __a, const signed char *__b)
-{
- return vec_perm((vector signed char)(0),
- vec_ld(__a, __b),
+static vector signed char __ATTRS_o_ai vec_lvrx(int __a,
+ const signed char *__b) {
+ return vec_perm((vector signed char)(0), vec_ld(__a, __b),
vec_lvsl(__a, __b));
}
-static vector signed char __ATTRS_o_ai
-vec_lvrx(int __a, const vector signed char *__b)
-{
- return vec_perm((vector signed char)(0),
- vec_ld(__a, __b),
+static vector signed char __ATTRS_o_ai vec_lvrx(int __a,
+ const vector signed char *__b) {
+ return vec_perm((vector signed char)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvrx(int __a, const unsigned char *__b)
-{
- return vec_perm((vector unsigned char)(0),
- vec_ld(__a, __b),
+static vector unsigned char __ATTRS_o_ai vec_lvrx(int __a,
+ const unsigned char *__b) {
+ return vec_perm((vector unsigned char)(0), vec_ld(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned char __ATTRS_o_ai
-vec_lvrx(int __a, const vector unsigned char *__b)
-{
- return vec_perm((vector unsigned char)(0),
- vec_ld(__a, __b),
+vec_lvrx(int __a, const vector unsigned char *__b) {
+ return vec_perm((vector unsigned char)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool char __ATTRS_o_ai
-vec_lvrx(int __a, const vector bool char *__b)
-{
- return vec_perm((vector bool char)(0),
- vec_ld(__a, __b),
+static vector bool char __ATTRS_o_ai vec_lvrx(int __a,
+ const vector bool char *__b) {
+ return vec_perm((vector bool char)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector short __ATTRS_o_ai
-vec_lvrx(int __a, const short *__b)
-{
- return vec_perm((vector short)(0),
- vec_ld(__a, __b),
- vec_lvsl(__a, __b));
+static vector short __ATTRS_o_ai vec_lvrx(int __a, const short *__b) {
+ return vec_perm((vector short)(0), vec_ld(__a, __b), vec_lvsl(__a, __b));
}
-static vector short __ATTRS_o_ai
-vec_lvrx(int __a, const vector short *__b)
-{
- return vec_perm((vector short)(0),
- vec_ld(__a, __b),
+static vector short __ATTRS_o_ai vec_lvrx(int __a, const vector short *__b) {
+ return vec_perm((vector short)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvrx(int __a, const unsigned short *__b)
-{
- return vec_perm((vector unsigned short)(0),
- vec_ld(__a, __b),
+static vector unsigned short __ATTRS_o_ai vec_lvrx(int __a,
+ const unsigned short *__b) {
+ return vec_perm((vector unsigned short)(0), vec_ld(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned short __ATTRS_o_ai
-vec_lvrx(int __a, const vector unsigned short *__b)
-{
- return vec_perm((vector unsigned short)(0),
- vec_ld(__a, __b),
+vec_lvrx(int __a, const vector unsigned short *__b) {
+ return vec_perm((vector unsigned short)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool short __ATTRS_o_ai
-vec_lvrx(int __a, const vector bool short *__b)
-{
- return vec_perm((vector bool short)(0),
- vec_ld(__a, __b),
+static vector bool short __ATTRS_o_ai vec_lvrx(int __a,
+ const vector bool short *__b) {
+ return vec_perm((vector bool short)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector pixel __ATTRS_o_ai
-vec_lvrx(int __a, const vector pixel *__b)
-{
- return vec_perm((vector pixel)(0),
- vec_ld(__a, __b),
+static vector pixel __ATTRS_o_ai vec_lvrx(int __a, const vector pixel *__b) {
+ return vec_perm((vector pixel)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector int __ATTRS_o_ai
-vec_lvrx(int __a, const int *__b)
-{
- return vec_perm((vector int)(0),
- vec_ld(__a, __b),
- vec_lvsl(__a, __b));
+static vector int __ATTRS_o_ai vec_lvrx(int __a, const int *__b) {
+ return vec_perm((vector int)(0), vec_ld(__a, __b), vec_lvsl(__a, __b));
}
-static vector int __ATTRS_o_ai
-vec_lvrx(int __a, const vector int *__b)
-{
- return vec_perm((vector int)(0),
- vec_ld(__a, __b),
+static vector int __ATTRS_o_ai vec_lvrx(int __a, const vector int *__b) {
+ return vec_perm((vector int)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvrx(int __a, const unsigned int *__b)
-{
- return vec_perm((vector unsigned int)(0),
- vec_ld(__a, __b),
+static vector unsigned int __ATTRS_o_ai vec_lvrx(int __a,
+ const unsigned int *__b) {
+ return vec_perm((vector unsigned int)(0), vec_ld(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned int __ATTRS_o_ai
-vec_lvrx(int __a, const vector unsigned int *__b)
-{
- return vec_perm((vector unsigned int)(0),
- vec_ld(__a, __b),
+vec_lvrx(int __a, const vector unsigned int *__b) {
+ return vec_perm((vector unsigned int)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool int __ATTRS_o_ai
-vec_lvrx(int __a, const vector bool int *__b)
-{
- return vec_perm((vector bool int)(0),
- vec_ld(__a, __b),
+static vector bool int __ATTRS_o_ai vec_lvrx(int __a,
+ const vector bool int *__b) {
+ return vec_perm((vector bool int)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector float __ATTRS_o_ai
-vec_lvrx(int __a, const float *__b)
-{
- return vec_perm((vector float)(0),
- vec_ld(__a, __b),
- vec_lvsl(__a, __b));
+static vector float __ATTRS_o_ai vec_lvrx(int __a, const float *__b) {
+ return vec_perm((vector float)(0), vec_ld(__a, __b), vec_lvsl(__a, __b));
}
-static vector float __ATTRS_o_ai
-vec_lvrx(int __a, const vector float *__b)
-{
- return vec_perm((vector float)(0),
- vec_ld(__a, __b),
+static vector float __ATTRS_o_ai vec_lvrx(int __a, const vector float *__b) {
+ return vec_perm((vector float)(0), vec_ld(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
/* vec_lvrxl */
-static vector signed char __ATTRS_o_ai
-vec_lvrxl(int __a, const signed char *__b)
-{
- return vec_perm((vector signed char)(0),
- vec_ldl(__a, __b),
+static vector signed char __ATTRS_o_ai vec_lvrxl(int __a,
+ const signed char *__b) {
+ return vec_perm((vector signed char)(0), vec_ldl(__a, __b),
vec_lvsl(__a, __b));
}
static vector signed char __ATTRS_o_ai
-vec_lvrxl(int __a, const vector signed char *__b)
-{
- return vec_perm((vector signed char)(0),
- vec_ldl(__a, __b),
+vec_lvrxl(int __a, const vector signed char *__b) {
+ return vec_perm((vector signed char)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned char __ATTRS_o_ai
-vec_lvrxl(int __a, const unsigned char *__b)
-{
- return vec_perm((vector unsigned char)(0),
- vec_ldl(__a, __b),
+static vector unsigned char __ATTRS_o_ai vec_lvrxl(int __a,
+ const unsigned char *__b) {
+ return vec_perm((vector unsigned char)(0), vec_ldl(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned char __ATTRS_o_ai
-vec_lvrxl(int __a, const vector unsigned char *__b)
-{
- return vec_perm((vector unsigned char)(0),
- vec_ldl(__a, __b),
+vec_lvrxl(int __a, const vector unsigned char *__b) {
+ return vec_perm((vector unsigned char)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool char __ATTRS_o_ai
-vec_lvrxl(int __a, const vector bool char *__b)
-{
- return vec_perm((vector bool char)(0),
- vec_ldl(__a, __b),
+static vector bool char __ATTRS_o_ai vec_lvrxl(int __a,
+ const vector bool char *__b) {
+ return vec_perm((vector bool char)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector short __ATTRS_o_ai
-vec_lvrxl(int __a, const short *__b)
-{
- return vec_perm((vector short)(0),
- vec_ldl(__a, __b),
- vec_lvsl(__a, __b));
+static vector short __ATTRS_o_ai vec_lvrxl(int __a, const short *__b) {
+ return vec_perm((vector short)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b));
}
-static vector short __ATTRS_o_ai
-vec_lvrxl(int __a, const vector short *__b)
-{
- return vec_perm((vector short)(0),
- vec_ldl(__a, __b),
+static vector short __ATTRS_o_ai vec_lvrxl(int __a, const vector short *__b) {
+ return vec_perm((vector short)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned short __ATTRS_o_ai
-vec_lvrxl(int __a, const unsigned short *__b)
-{
- return vec_perm((vector unsigned short)(0),
- vec_ldl(__a, __b),
+static vector unsigned short __ATTRS_o_ai vec_lvrxl(int __a,
+ const unsigned short *__b) {
+ return vec_perm((vector unsigned short)(0), vec_ldl(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned short __ATTRS_o_ai
-vec_lvrxl(int __a, const vector unsigned short *__b)
-{
- return vec_perm((vector unsigned short)(0),
- vec_ldl(__a, __b),
+vec_lvrxl(int __a, const vector unsigned short *__b) {
+ return vec_perm((vector unsigned short)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool short __ATTRS_o_ai
-vec_lvrxl(int __a, const vector bool short *__b)
-{
- return vec_perm((vector bool short)(0),
- vec_ldl(__a, __b),
+static vector bool short __ATTRS_o_ai vec_lvrxl(int __a,
+ const vector bool short *__b) {
+ return vec_perm((vector bool short)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector pixel __ATTRS_o_ai
-vec_lvrxl(int __a, const vector pixel *__b)
-{
- return vec_perm((vector pixel)(0),
- vec_ldl(__a, __b),
+static vector pixel __ATTRS_o_ai vec_lvrxl(int __a, const vector pixel *__b) {
+ return vec_perm((vector pixel)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector int __ATTRS_o_ai
-vec_lvrxl(int __a, const int *__b)
-{
- return vec_perm((vector int)(0),
- vec_ldl(__a, __b),
- vec_lvsl(__a, __b));
+static vector int __ATTRS_o_ai vec_lvrxl(int __a, const int *__b) {
+ return vec_perm((vector int)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b));
}
-static vector int __ATTRS_o_ai
-vec_lvrxl(int __a, const vector int *__b)
-{
- return vec_perm((vector int)(0),
- vec_ldl(__a, __b),
+static vector int __ATTRS_o_ai vec_lvrxl(int __a, const vector int *__b) {
+ return vec_perm((vector int)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector unsigned int __ATTRS_o_ai
-vec_lvrxl(int __a, const unsigned int *__b)
-{
- return vec_perm((vector unsigned int)(0),
- vec_ldl(__a, __b),
+static vector unsigned int __ATTRS_o_ai vec_lvrxl(int __a,
+ const unsigned int *__b) {
+ return vec_perm((vector unsigned int)(0), vec_ldl(__a, __b),
vec_lvsl(__a, __b));
}
static vector unsigned int __ATTRS_o_ai
-vec_lvrxl(int __a, const vector unsigned int *__b)
-{
- return vec_perm((vector unsigned int)(0),
- vec_ldl(__a, __b),
+vec_lvrxl(int __a, const vector unsigned int *__b) {
+ return vec_perm((vector unsigned int)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector bool int __ATTRS_o_ai
-vec_lvrxl(int __a, const vector bool int *__b)
-{
- return vec_perm((vector bool int)(0),
- vec_ldl(__a, __b),
+static vector bool int __ATTRS_o_ai vec_lvrxl(int __a,
+ const vector bool int *__b) {
+ return vec_perm((vector bool int)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
-static vector float __ATTRS_o_ai
-vec_lvrxl(int __a, const float *__b)
-{
- return vec_perm((vector float)(0),
- vec_ldl(__a, __b),
- vec_lvsl(__a, __b));
+static vector float __ATTRS_o_ai vec_lvrxl(int __a, const float *__b) {
+ return vec_perm((vector float)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b));
}
-static vector float __ATTRS_o_ai
-vec_lvrxl(int __a, const vector float *__b)
-{
- return vec_perm((vector float)(0),
- vec_ldl(__a, __b),
+static vector float __ATTRS_o_ai vec_lvrxl(int __a, const vector float *__b) {
+ return vec_perm((vector float)(0), vec_ldl(__a, __b),
vec_lvsl(__a, (unsigned char *)__b));
}
/* vec_stvlx */
-static void __ATTRS_o_ai
-vec_stvlx(vector signed char __a, int __b, signed char *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector signed char __a, int __b,
+ signed char *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector signed char __a, int __b, vector signed char *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector signed char __a, int __b,
+ vector signed char *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned char __a, int __b, unsigned char *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned char __a, int __b,
+ unsigned char *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector bool char __a, int __b, vector bool char *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector bool char __a, int __b,
+ vector bool char *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector short __a, int __b, short *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector short __a, int __b, short *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector short __a, int __b, vector short *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector short __a, int __b,
+ vector short *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned short __a, int __b, unsigned short *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned short __a, int __b,
+ unsigned short *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector bool short __a, int __b, vector bool short *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector bool short __a, int __b,
+ vector bool short *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector pixel __a, int __b, vector pixel *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector pixel __a, int __b,
+ vector pixel *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector int __a, int __b, int *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector int __a, int __b, int *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector int __a, int __b, vector int *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector int __a, int __b, vector int *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned int __a, int __b, unsigned int *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned int __a, int __b,
+ unsigned int *__c) {
+ return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector bool int __a, int __b, vector bool int *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector bool int __a, int __b,
+ vector bool int *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlx(vector float __a, int __b, vector float *__c)
-{
- return vec_st(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlx(vector float __a, int __b,
+ vector float *__c) {
+ return vec_st(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
/* vec_stvlxl */
-static void __ATTRS_o_ai
-vec_stvlxl(vector signed char __a, int __b, signed char *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector signed char __a, int __b,
+ signed char *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector signed char __a, int __b, vector signed char *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector signed char __a, int __b,
+ vector signed char *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned char __a, int __b, unsigned char *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned char __a, int __b,
+ unsigned char *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector bool char __a, int __b, vector bool char *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector bool char __a, int __b,
+ vector bool char *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector short __a, int __b, short *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector short __a, int __b, short *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector short __a, int __b, vector short *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector short __a, int __b,
+ vector short *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned short __a, int __b, unsigned short *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned short __a, int __b,
+ unsigned short *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector bool short __a, int __b, vector bool short *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector bool short __a, int __b,
+ vector bool short *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector pixel __a, int __b, vector pixel *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector pixel __a, int __b,
+ vector pixel *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector int __a, int __b, int *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector int __a, int __b, int *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector int __a, int __b, vector int *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector int __a, int __b, vector int *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned int __a, int __b, unsigned int *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned int __a, int __b,
+ unsigned int *__c) {
+ return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector bool int __a, int __b, vector bool int *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector bool int __a, int __b,
+ vector bool int *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvlxl(vector float __a, int __b, vector float *__c)
-{
- return vec_stl(vec_perm(vec_lvrx(__b, __c),
- __a,
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvlxl(vector float __a, int __b,
+ vector float *__c) {
+ return vec_stl(
+ vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
/* vec_stvrx */
-static void __ATTRS_o_ai
-vec_stvrx(vector signed char __a, int __b, signed char *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector signed char __a, int __b,
+ signed char *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector signed char __a, int __b, vector signed char *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector signed char __a, int __b,
+ vector signed char *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned char __a, int __b, unsigned char *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned char __a, int __b,
+ unsigned char *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector bool char __a, int __b, vector bool char *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector bool char __a, int __b,
+ vector bool char *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector short __a, int __b, short *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector short __a, int __b, short *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector short __a, int __b, vector short *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector short __a, int __b,
+ vector short *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned short __a, int __b, unsigned short *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned short __a, int __b,
+ unsigned short *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector bool short __a, int __b, vector bool short *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector bool short __a, int __b,
+ vector bool short *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector pixel __a, int __b, vector pixel *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector pixel __a, int __b,
+ vector pixel *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector int __a, int __b, int *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector int __a, int __b, int *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector int __a, int __b, vector int *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector int __a, int __b, vector int *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned int __a, int __b, unsigned int *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned int __a, int __b,
+ unsigned int *__c) {
+ return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector bool int __a, int __b, vector bool int *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector bool int __a, int __b,
+ vector bool int *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrx(vector float __a, int __b, vector float *__c)
-{
- return vec_st(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrx(vector float __a, int __b,
+ vector float *__c) {
+ return vec_st(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
/* vec_stvrxl */
-static void __ATTRS_o_ai
-vec_stvrxl(vector signed char __a, int __b, signed char *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector signed char __a, int __b,
+ signed char *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector signed char __a, int __b, vector signed char *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector signed char __a, int __b,
+ vector signed char *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned char __a, int __b, unsigned char *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned char __a, int __b,
+ unsigned char *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned char __a, int __b, vector unsigned char *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned char __a, int __b,
+ vector unsigned char *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector bool char __a, int __b, vector bool char *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector bool char __a, int __b,
+ vector bool char *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector short __a, int __b, short *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector short __a, int __b, short *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector short __a, int __b, vector short *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector short __a, int __b,
+ vector short *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned short __a, int __b, unsigned short *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned short __a, int __b,
+ unsigned short *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned short __a, int __b, vector unsigned short *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned short __a, int __b,
+ vector unsigned short *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector bool short __a, int __b, vector bool short *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector bool short __a, int __b,
+ vector bool short *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector pixel __a, int __b, vector pixel *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector pixel __a, int __b,
+ vector pixel *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector int __a, int __b, int *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector int __a, int __b, int *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector int __a, int __b, vector int *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector int __a, int __b, vector int *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned int __a, int __b, unsigned int *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, __c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned int __a, int __b,
+ unsigned int *__c) {
+ return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b,
+ __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector unsigned int __a, int __b, vector unsigned int *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector unsigned int __a, int __b,
+ vector unsigned int *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector bool int __a, int __b, vector bool int *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector bool int __a, int __b,
+ vector bool int *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
-static void __ATTRS_o_ai
-vec_stvrxl(vector float __a, int __b, vector float *__c)
-{
- return vec_stl(vec_perm(__a,
- vec_lvlx(__b, __c),
- vec_lvsr(__b, (unsigned char *)__c)),
- __b, __c);
+static void __ATTRS_o_ai vec_stvrxl(vector float __a, int __b,
+ vector float *__c) {
+ return vec_stl(
+ vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)),
+ __b, __c);
}
/* vec_promote */
-static vector signed char __ATTRS_o_ai
-vec_promote(signed char __a, int __b)
-{
+static vector signed char __ATTRS_o_ai vec_promote(signed char __a, int __b) {
vector signed char __res = (vector signed char)(0);
__res[__b] = __a;
return __res;
}
-static vector unsigned char __ATTRS_o_ai
-vec_promote(unsigned char __a, int __b)
-{
+static vector unsigned char __ATTRS_o_ai vec_promote(unsigned char __a,
+ int __b) {
vector unsigned char __res = (vector unsigned char)(0);
__res[__b] = __a;
return __res;
}
-static vector short __ATTRS_o_ai
-vec_promote(short __a, int __b)
-{
+static vector short __ATTRS_o_ai vec_promote(short __a, int __b) {
vector short __res = (vector short)(0);
__res[__b] = __a;
return __res;
}
-static vector unsigned short __ATTRS_o_ai
-vec_promote(unsigned short __a, int __b)
-{
+static vector unsigned short __ATTRS_o_ai vec_promote(unsigned short __a,
+ int __b) {
vector unsigned short __res = (vector unsigned short)(0);
__res[__b] = __a;
return __res;
}
-static vector int __ATTRS_o_ai
-vec_promote(int __a, int __b)
-{
+static vector int __ATTRS_o_ai vec_promote(int __a, int __b) {
vector int __res = (vector int)(0);
__res[__b] = __a;
return __res;
}
-static vector unsigned int __ATTRS_o_ai
-vec_promote(unsigned int __a, int __b)
-{
+static vector unsigned int __ATTRS_o_ai vec_promote(unsigned int __a, int __b) {
vector unsigned int __res = (vector unsigned int)(0);
__res[__b] = __a;
return __res;
}
-static vector float __ATTRS_o_ai
-vec_promote(float __a, int __b)
-{
+static vector float __ATTRS_o_ai vec_promote(float __a, int __b) {
vector float __res = (vector float)(0);
__res[__b] = __a;
return __res;
@@ -10703,45 +11175,29 @@ vec_promote(float __a, int __b)
/* vec_splats */
-static vector signed char __ATTRS_o_ai
-vec_splats(signed char __a)
-{
+static vector signed char __ATTRS_o_ai vec_splats(signed char __a) {
return (vector signed char)(__a);
}
-static vector unsigned char __ATTRS_o_ai
-vec_splats(unsigned char __a)
-{
+static vector unsigned char __ATTRS_o_ai vec_splats(unsigned char __a) {
return (vector unsigned char)(__a);
}
-static vector short __ATTRS_o_ai
-vec_splats(short __a)
-{
+static vector short __ATTRS_o_ai vec_splats(short __a) {
return (vector short)(__a);
}
-static vector unsigned short __ATTRS_o_ai
-vec_splats(unsigned short __a)
-{
+static vector unsigned short __ATTRS_o_ai vec_splats(unsigned short __a) {
return (vector unsigned short)(__a);
}
-static vector int __ATTRS_o_ai
-vec_splats(int __a)
-{
- return (vector int)(__a);
-}
+static vector int __ATTRS_o_ai vec_splats(int __a) { return (vector int)(__a); }
-static vector unsigned int __ATTRS_o_ai
-vec_splats(unsigned int __a)
-{
+static vector unsigned int __ATTRS_o_ai vec_splats(unsigned int __a) {
return (vector unsigned int)(__a);
}
-static vector float __ATTRS_o_ai
-vec_splats(float __a)
-{
+static vector float __ATTRS_o_ai vec_splats(float __a) {
return (vector float)(__a);
}
@@ -10749,1918 +11205,2145 @@ vec_splats(float __a)
/* vec_all_eq */
-static int __ATTRS_o_ai
-vec_all_eq(vector signed char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector signed char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned char __a, vector unsigned char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool char __a, vector unsigned char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_eq(vector short __a, vector short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_eq(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_LT, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool short __a, vector short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector pixel __a, vector pixel __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_eq(vector pixel __a, vector pixel __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_eq(vector int __a, vector int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_eq(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_LT, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_eq(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_eq(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_eq(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_eq(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, __a, (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector bool long long __a,
+ vector long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_eq(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a,
+ (vector long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_eq(vector float __a, vector float __b) {
return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __b);
}
/* vec_all_ge */
-static int __ATTRS_o_ai
-vec_all_ge(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector signed char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __b, (vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector short)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b, __a);
+static int __ATTRS_o_ai vec_all_ge(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __b, (vector unsigned short)__a);
+static int __ATTRS_o_ai vec_all_ge(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __b,
+ (vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector unsigned int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_ge(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __b, (vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_ge(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_ge(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __b, __a);
+}
+static int __ATTRS_o_ai vec_all_ge(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, (vector signed long long)__b,
+ __a);
+}
+
+static int __ATTRS_o_ai vec_all_ge(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_all_ge(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b,
+ __a);
+}
+
+static int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_ge(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_LT, __a, __b);
}
/* vec_all_gt */
-static int __ATTRS_o_ai
-vec_all_gt(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector signed char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __a, (vector signed char)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, __a, (vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __a, (vector unsigned short)__b);
+static int __ATTRS_o_ai vec_all_gt(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __a,
+ (vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a, __b);
+static int __ATTRS_o_ai vec_all_gt(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector unsigned int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __a, (vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_gt(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a, __b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_gt(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_gt(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __a, __b);
+}
+static int __ATTRS_o_ai vec_all_gt(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_gt(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_all_gt(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, __a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a,
+ __b);
+}
+
+static int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_gt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __a, __b);
}
/* vec_all_in */
static int __attribute__((__always_inline__))
-vec_all_in(vector float __a, vector float __b)
-{
+vec_all_in(vector float __a, vector float __b) {
return __builtin_altivec_vcmpbfp_p(__CR6_EQ, __a, __b);
}
/* vec_all_le */
-static int __ATTRS_o_ai
-vec_all_le(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector signed char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __a, (vector signed char)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __a, (vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __a, (vector unsigned short)__b);
+static int __ATTRS_o_ai vec_all_le(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __a,
+ (vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a, __b);
+static int __ATTRS_o_ai vec_all_le(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector unsigned int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __a, (vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_le(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a, __b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_all_le(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_all_le(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_le(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a,
+ __b);
+}
+
+static int __ATTRS_o_ai vec_all_le(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_le(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_LT, __b, __a);
}
/* vec_all_lt */
-static int __ATTRS_o_ai
-vec_all_lt(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector signed char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector signed char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned char __a, vector bool char __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector unsigned char __a,
+ vector bool char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector bool char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT, __b, (vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector short)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b, __a);
+static int __ATTRS_o_ai vec_all_lt(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __b, (vector unsigned short)__a);
+static int __ATTRS_o_ai vec_all_lt(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __b,
+ (vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector unsigned int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector unsigned int __a,
+ vector bool int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_all_lt(vector bool int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __b, (vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_all_lt(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_lt(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, (vector signed long long)__b,
+ __a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b,
+ __a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, __b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_lt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __b, __a);
}
/* vec_all_nan */
-static int __attribute__((__always_inline__))
-vec_all_nan(vector float __a)
-{
+static int __attribute__((__always_inline__)) vec_all_nan(vector float __a) {
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __a);
}
/* vec_all_ne */
-static int __ATTRS_o_ai
-vec_all_ne(vector signed char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector signed char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned char __a, vector unsigned char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool char __a, vector unsigned char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_all_ne(vector short __a, vector short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_all_ne(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_EQ, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool short __a, vector short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector pixel __a, vector pixel __b)
-{
- return
- __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b);
+static int __ATTRS_o_ai vec_all_ne(vector pixel __a, vector pixel __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a,
+ (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_all_ne(vector int __a, vector int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_EQ, __a, __b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_all_ne(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_EQ, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_ne(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_all_ne(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_all_ne(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_all_ne(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_all_ne(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a,
+ (vector signed long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_all_ne(vector float __a, vector float __b) {
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __b);
}
/* vec_all_nge */
static int __attribute__((__always_inline__))
-vec_all_nge(vector float __a, vector float __b)
-{
+vec_all_nge(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __a, __b);
}
/* vec_all_ngt */
static int __attribute__((__always_inline__))
-vec_all_ngt(vector float __a, vector float __b)
-{
+vec_all_ngt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __a, __b);
}
/* vec_all_nle */
static int __attribute__((__always_inline__))
-vec_all_nle(vector float __a, vector float __b)
-{
+vec_all_nle(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __b, __a);
}
/* vec_all_nlt */
static int __attribute__((__always_inline__))
-vec_all_nlt(vector float __a, vector float __b)
-{
+vec_all_nlt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __b, __a);
}
/* vec_all_numeric */
static int __attribute__((__always_inline__))
-vec_all_numeric(vector float __a)
-{
+vec_all_numeric(vector float __a) {
return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __a);
}
/* vec_any_eq */
-static int __ATTRS_o_ai
-vec_any_eq(vector signed char __a, vector signed char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector signed char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector signed char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool char __a, vector signed char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_eq(vector short __a, vector short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_eq(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector pixel __a, vector pixel __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_eq(vector pixel __a, vector pixel __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_eq(vector int __a, vector int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_eq(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned int __a, vector unsigned int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_eq(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector unsigned int __a, vector bool int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_eq(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool int __a, vector int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool int __a, vector unsigned int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector bool int __a, vector bool int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_eq(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_eq(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_eq(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_eq(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_eq(vector float __a, vector float __b) {
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __b);
}
/* vec_any_ge */
-static int __ATTRS_o_ai
-vec_any_ge(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)__b, __a);
+static int __ATTRS_o_ai vec_any_ge(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b, __a);
+static int __ATTRS_o_ai vec_any_ge(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool char __a, vector unsigned char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __b, (vector unsigned char)__a);
+static int __ATTRS_o_ai vec_any_ge(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __b,
+ (vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector short)__b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b, __a);
+static int __ATTRS_o_ai vec_any_ge(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __b, (vector unsigned short)__a);
+static int __ATTRS_o_ai vec_any_ge(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __b,
+ (vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_any_ge(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b, __a);
+static int __ATTRS_o_ai vec_any_ge(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __b, (vector unsigned int)__a);
+static int __ATTRS_o_ai vec_any_ge(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __b,
+ (vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_ge(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_ge(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV,
+ (vector signed long long)__b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_ge(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __a, __b);
}
/* vec_any_gt */
-static int __ATTRS_o_ai
-vec_any_gt(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __a, (vector signed char)__b);
+static int __ATTRS_o_ai vec_any_gt(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __a,
+ (vector signed char)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __a, (vector unsigned char)__b);
+static int __ATTRS_o_ai vec_any_gt(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __a,
+ (vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a, __b);
+static int __ATTRS_o_ai vec_any_gt(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __a, (vector unsigned short)__b);
+static int __ATTRS_o_ai vec_any_gt(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __a,
+ (vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a, __b);
+static int __ATTRS_o_ai vec_any_gt(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_any_gt(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __a, (vector unsigned int)__b);
+static int __ATTRS_o_ai vec_any_gt(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __a,
+ (vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a, __b);
+static int __ATTRS_o_ai vec_any_gt(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_gt(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_gt(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_gt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __a, __b);
}
/* vec_any_le */
-static int __ATTRS_o_ai
-vec_any_le(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __a, (vector signed char)__b);
+static int __ATTRS_o_ai vec_any_le(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __a,
+ (vector signed char)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __a, (vector unsigned char)__b);
+static int __ATTRS_o_ai vec_any_le(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __a,
+ (vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a, __b);
+static int __ATTRS_o_ai vec_any_le(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
- (vector unsigned char)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a,
(vector unsigned char)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __a, (vector unsigned short)__b);
+static int __ATTRS_o_ai vec_any_le(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __a,
+ (vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a, __b);
+static int __ATTRS_o_ai vec_any_le(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
- (vector unsigned short)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a,
(vector unsigned short)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_any_le(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __a, (vector unsigned int)__b);
+static int __ATTRS_o_ai vec_any_le(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __a,
+ (vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a, __b);
+static int __ATTRS_o_ai vec_any_le(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a,
+ __b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
- (vector unsigned int)__a,
+static int __ATTRS_o_ai vec_any_le(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a,
(vector unsigned int)__b);
}
-static int __ATTRS_o_ai
-vec_any_le(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_le(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_le(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
+ (vector unsigned long long)__a,
+ (vector unsigned long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_le(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __b, __a);
}
/* vec_any_lt */
-static int __ATTRS_o_ai
-vec_any_lt(vector signed char __a, vector signed char __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector signed char __a,
+ vector signed char __b) {
return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector signed char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)__b, __a);
+static int __ATTRS_o_ai vec_any_lt(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned char __a, vector unsigned char __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector unsigned char __a,
+ vector unsigned char __b) {
return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b, __a);
+static int __ATTRS_o_ai vec_any_lt(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool char __a, vector signed char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __b, (vector unsigned char)__a);
+static int __ATTRS_o_ai vec_any_lt(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __b,
+ (vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool char __a, vector bool char __b)
-{
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
- (vector unsigned char)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b,
(vector unsigned char)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector short __a, vector short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector short)__b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned short __a, vector unsigned short __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector unsigned short __a,
+ vector unsigned short __b) {
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned short __a, vector bool short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b, __a);
+static int __ATTRS_o_ai vec_any_lt(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool short __a, vector unsigned short __b)
-{
- return
- __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __b, (vector unsigned short)__a);
+static int __ATTRS_o_ai vec_any_lt(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __b,
+ (vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
- (vector unsigned short)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b,
(vector unsigned short)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector int __a, vector int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector int)__b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned int __a, vector unsigned int __b)
-{
+static int __ATTRS_o_ai vec_any_lt(vector unsigned int __a,
+ vector unsigned int __b) {
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __b, __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector unsigned int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b, __a);
+static int __ATTRS_o_ai vec_any_lt(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b,
+ __a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool int __a, vector int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool int __a, vector unsigned int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __b, (vector unsigned int)__a);
+static int __ATTRS_o_ai vec_any_lt(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __b,
+ (vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector bool int __a, vector bool int __b)
-{
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
- (vector unsigned int)__b,
+static int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b,
(vector unsigned int)__a);
}
-static int __ATTRS_o_ai
-vec_any_lt(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_lt(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV,
+ (vector signed long long)__b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__b, __a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __b,
+ (vector unsigned long long)__a);
+}
+
+static int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
+ (vector unsigned long long)__b,
+ (vector unsigned long long)__a);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_lt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __b, __a);
}
/* vec_any_nan */
-static int __attribute__((__always_inline__))
-vec_any_nan(vector float __a)
-{
+static int __attribute__((__always_inline__)) vec_any_nan(vector float __a) {
return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __a);
}
/* vec_any_ne */
-static int __ATTRS_o_ai
-vec_any_ne(vector signed char __a, vector signed char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector signed char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector signed char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector signed char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector unsigned char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector unsigned char __a,
+ vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool char __a, vector signed char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool char __a,
+ vector signed char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool char __a, vector unsigned char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool char __a,
+ vector unsigned char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool char __a, vector bool char __b)
-{
- return
- __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool char __a, vector bool char __b) {
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a,
+ (vector char)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector short __a, vector short __b)
-{
+static int __ATTRS_o_ai vec_any_ne(vector short __a, vector short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector short __a, vector bool short __b)
-{
+static int __ATTRS_o_ai vec_any_ne(vector short __a, vector bool short __b) {
return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, __a, (vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector unsigned short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector unsigned short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool short __a, vector short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector bool short __a, vector short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool short __a, vector unsigned short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector bool short __a,
+ vector unsigned short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool short __a, vector bool short __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector bool short __a,
+ vector bool short __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector pixel __a, vector pixel __b)
-{
- return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
- (vector short)__a,
+static int __ATTRS_o_ai vec_any_ne(vector pixel __a, vector pixel __b) {
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a,
(vector short)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector int __a, vector int __b)
-{
+static int __ATTRS_o_ai vec_any_ne(vector int __a, vector int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, __a, __b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector int __a, vector bool int __b)
-{
+static int __ATTRS_o_ai vec_any_ne(vector int __a, vector bool int __b) {
return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, __a, (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned int __a, vector unsigned int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_ne(vector unsigned int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector unsigned int __a, vector bool int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_ne(vector unsigned int __a,
+ vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool int __a, vector int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool int __a, vector int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool int __a, vector unsigned int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool int __a,
+ vector unsigned int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector bool int __a, vector bool int __b)
-{
- return
- __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b);
+static int __ATTRS_o_ai vec_any_ne(vector bool int __a, vector bool int __b) {
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a,
+ (vector int)__b);
}
-static int __ATTRS_o_ai
-vec_any_ne(vector float __a, vector float __b)
-{
+#ifdef __POWER8_VECTOR__
+static int __ATTRS_o_ai vec_any_ne(vector signed long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, __a, __b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, (vector long long)__a,
+ (vector long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector signed long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, __a,
+ (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector unsigned long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector bool long long __a,
+ vector signed long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector bool long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+
+static int __ATTRS_o_ai vec_any_ne(vector bool long long __a,
+ vector bool long long __b) {
+ return __builtin_altivec_vcmpequd_p(
+ __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b);
+}
+#endif
+
+static int __ATTRS_o_ai vec_any_ne(vector float __a, vector float __b) {
return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __b);
}
/* vec_any_nge */
static int __attribute__((__always_inline__))
-vec_any_nge(vector float __a, vector float __b)
-{
+vec_any_nge(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __a, __b);
}
/* vec_any_ngt */
static int __attribute__((__always_inline__))
-vec_any_ngt(vector float __a, vector float __b)
-{
+vec_any_ngt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __a, __b);
}
/* vec_any_nle */
static int __attribute__((__always_inline__))
-vec_any_nle(vector float __a, vector float __b)
-{
+vec_any_nle(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __b, __a);
}
/* vec_any_nlt */
static int __attribute__((__always_inline__))
-vec_any_nlt(vector float __a, vector float __b)
-{
+vec_any_nlt(vector float __a, vector float __b) {
return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __b, __a);
}
/* vec_any_numeric */
static int __attribute__((__always_inline__))
-vec_any_numeric(vector float __a)
-{
+vec_any_numeric(vector float __a) {
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __a);
}
/* vec_any_out */
static int __attribute__((__always_inline__))
-vec_any_out(vector float __a, vector float __b)
-{
+vec_any_out(vector float __a, vector float __b) {
return __builtin_altivec_vcmpbfp_p(__CR6_EQ_REV, __a, __b);
}
+/* Power 8 Crypto functions
+Note: We diverge from the current GCC implementation with regard
+to cryptography and related functions as follows:
+- Only the SHA and AES instructions and builtins are disabled by -mno-crypto
+- The remaining ones are only available on Power8 and up so
+ require -mpower8-vector
+The justification for this is that export requirements require that
+Category:Vector.Crypto is optional (i.e. compliant hardware may not provide
+support). As a result, we need to be able to turn off support for those.
+The remaining ones (currently controlled by -mcrypto for GCC) still
+need to be provided on compliant hardware even if Vector.Crypto is not
+provided.
+FIXME: the naming convention for the builtins will be adjusted due
+to the inconsistency (__builtin_crypto_ prefix on builtins that cannot be
+removed with -mno-crypto). This is under development.
+*/
+#ifdef __CRYPTO__
+static vector unsigned long long __attribute__((__always_inline__))
+__builtin_crypto_vsbox(vector unsigned long long __a) {
+ return __builtin_altivec_crypto_vsbox(__a);
+}
+
+static vector unsigned long long __attribute__((__always_inline__))
+__builtin_crypto_vcipher(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_crypto_vcipher(__a, __b);
+}
+
+static vector unsigned long long __attribute__((__always_inline__))
+__builtin_crypto_vcipherlast(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_crypto_vcipherlast(__a, __b);
+}
+
+static vector unsigned long long __attribute__((__always_inline__))
+__builtin_crypto_vncipher(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_crypto_vncipher(__a, __b);
+}
+
+static vector unsigned long long __attribute__((__always_inline__))
+__builtin_crypto_vncipherlast(vector unsigned long long __a,
+ vector unsigned long long __b) {
+ return __builtin_altivec_crypto_vncipherlast(__a, __b);
+}
+
+#define __builtin_crypto_vshasigmad __builtin_altivec_crypto_vshasigmad
+#define __builtin_crypto_vshasigmaw __builtin_altivec_crypto_vshasigmaw
+#endif
+
+#ifdef __POWER8_VECTOR__
+static vector unsigned char __ATTRS_o_ai
+__builtin_crypto_vpermxor(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return __builtin_altivec_crypto_vpermxor(__a, __b, __c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+__builtin_crypto_vpermxor(vector unsigned short __a, vector unsigned short __b,
+ vector unsigned short __c) {
+ return (vector unsigned short)__builtin_altivec_crypto_vpermxor(
+ (vector unsigned char)__a, (vector unsigned char)__b,
+ (vector unsigned char)__c);
+}
+
+static vector unsigned int __ATTRS_o_ai __builtin_crypto_vpermxor(
+ vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) {
+ return (vector unsigned int)__builtin_altivec_crypto_vpermxor(
+ (vector unsigned char)__a, (vector unsigned char)__b,
+ (vector unsigned char)__c);
+}
+
+static vector unsigned long long __ATTRS_o_ai __builtin_crypto_vpermxor(
+ vector unsigned long long __a, vector unsigned long long __b,
+ vector unsigned long long __c) {
+ return (vector unsigned long long)__builtin_altivec_crypto_vpermxor(
+ (vector unsigned char)__a, (vector unsigned char)__b,
+ (vector unsigned char)__c);
+}
+
+static vector unsigned char __ATTRS_o_ai
+__builtin_crypto_vpmsumb(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_crypto_vpmsumb(__a, __b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+__builtin_crypto_vpmsumb(vector unsigned short __a, vector unsigned short __b) {
+ return __builtin_altivec_crypto_vpmsumh(__a, __b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+__builtin_crypto_vpmsumb(vector unsigned int __a, vector unsigned int __b) {
+ return __builtin_altivec_crypto_vpmsumw(__a, __b);
+}
+
+static vector unsigned long long __ATTRS_o_ai __builtin_crypto_vpmsumb(
+ vector unsigned long long __a, vector unsigned long long __b) {
+ return __builtin_altivec_crypto_vpmsumd(__a, __b);
+}
+
+static vector signed char __ATTRS_o_ai vec_vgbbd (vector signed char __a)
+{
+ return __builtin_altivec_vgbbd((vector unsigned char) __a);
+}
+
+static vector unsigned char __ATTRS_o_ai vec_vgbbd (vector unsigned char __a)
+{
+ return __builtin_altivec_vgbbd(__a);
+}
+
+static vector long long __ATTRS_o_ai
+vec_vbpermq (vector signed char __a, vector signed char __b)
+{
+ return __builtin_altivec_vbpermq((vector unsigned char) __a,
+ (vector unsigned char) __b);
+}
+
+static vector long long __ATTRS_o_ai
+vec_vbpermq (vector unsigned char __a, vector unsigned char __b)
+{
+ return __builtin_altivec_vbpermq(__a, __b);
+}
+#endif
+
#undef __ATTRS_o_ai
#endif /* __ALTIVEC_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
index d87b9cd..4d0e770 100644
--- a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
@@ -30,39 +30,186 @@
#include <pmmintrin.h>
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
+/// integer vector operand at the index idx and of the length len.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm_extracti_si64(__m128i x, const int len, const int idx);
+/// \endcode
+///
+/// \code
+/// This intrinsic corresponds to the \c EXTRQ instruction.
+/// \endcode
+///
+/// \param x
+/// The value from which bits are extracted.
+/// \param len
+/// Bits [5:0] specify the length; the other bits are ignored. If bits [5:0]
+/// are zero, the length is interpreted as 64.
+/// \param idx
+/// Bits [5:0] specify the index of the least significant bit; the other
+/// bits are ignored. If the sum of the index and length is greater than
+/// 64, the result is undefined. If the length and index are both zero,
+/// bits [63:0] of parameter x are extracted. If the length is zero
+/// but the index is non-zero, the result is undefined.
+/// \returns A 128-bit integer vector whose lower 64 bits contain the bits
+/// extracted from the source operand.
#define _mm_extracti_si64(x, len, idx) \
((__m128i)__builtin_ia32_extrqi((__v2di)(__m128i)(x), \
(char)(len), (char)(idx)))
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
+/// integer vector operand at the index and of the length specified by __y.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// This intrinsic corresponds to the \c EXTRQ instruction.
+/// \endcode
+///
+/// \param __x
+/// The value from which bits are extracted.
+/// \param __y
+/// Specifies the index of the least significant bit at [13:8]
+/// and the length at [5:0]; all other bits are ignored.
+/// If bits [5:0] are zero, the length is interpreted as 64.
+/// If the sum of the index and length is greater than 64, the result is
+/// undefined. If the length and index are both zero, bits [63:0] of
+/// parameter __x are extracted. If the length is zero but the index is
+/// non-zero, the result is undefined.
+/// \returns A 128-bit vector whose lower 64 bits contain the bits extracted
+/// from the source operand.
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_extract_si64(__m128i __x, __m128i __y)
{
return (__m128i)__builtin_ia32_extrq((__v2di)__x, (__v16qi)__y);
}
+/// \brief Inserts bits of a specified length from the source integer vector
+/// y into the lower 64 bits of the destination integer vector x at the
+/// index idx and of the length len.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm_inserti_si64(__m128i x, __m128i y, const int len,
+/// const int idx);
+/// \endcode
+///
+/// \code
+/// This intrinsic corresponds to the \c INSERTQ instruction.
+/// \endcode
+///
+/// \param x
+/// The destination operand where bits will be inserted. The inserted bits
+/// are defined by the length len and by the index idx specifying the least
+/// significant bit.
+/// \param y
+/// The source operand containing the bits to be extracted. The extracted
+/// bits are the least significant bits of operand y of length len.
+/// \param len
+/// Bits [5:0] specify the length; the other bits are ignored. If bits [5:0]
+/// are zero, the length is interpreted as 64.
+/// \param idx
+/// Bits [5:0] specify the index of the least significant bit; the other
+/// bits are ignored. If the sum of the index and length is greater than
+/// 64, the result is undefined. If the length and index are both zero,
+/// bits [63:0] of parameter y are inserted into parameter x. If the
+/// length is zero but the index is non-zero, the result is undefined.
+/// \returns A 128-bit integer vector containing the original lower 64-bits
+/// of destination operand x with the specified bitfields replaced by the
+/// lower bits of source operand y. The upper 64 bits of the return value
+/// are undefined.
+
#define _mm_inserti_si64(x, y, len, idx) \
((__m128i)__builtin_ia32_insertqi((__v2di)(__m128i)(x), \
(__v2di)(__m128i)(y), \
(char)(len), (char)(idx)))
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+/// \brief Inserts bits of a specified length from the source integer vector
+/// __y into the lower 64 bits of the destination integer vector __x at
+/// the index and of the length specified by __y.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// This intrinsic corresponds to the \c INSERTQ instruction.
+/// \endcode
+///
+/// \param __x
+/// The destination operand where bits will be inserted. The inserted bits
+/// are defined by the length and by the index of the least significant bit
+/// specified by operand __y.
+/// \param __y
+/// The source operand containing the bits to be extracted. The extracted
+/// bits are the least significant bits of operand __y with length specified
+/// by bits [69:64]. These are inserted into the destination at the index
+/// specified by bits [77:72]; all other bits are ignored.
+/// If bits [69:64] are zero, the length is interpreted as 64.
+/// If the sum of the index and length is greater than 64, the result is
+/// undefined. If the length and index are both zero, bits [63:0] of
+/// parameter __y are inserted into parameter __x. If the length
+/// is zero but the index is non-zero, the result is undefined.
+/// \returns A 128-bit integer vector containing the original lower 64-bits
+/// of destination operand __x with the specified bitfields replaced by the
+/// lower bits of source operand __y. The upper 64 bits of the return value
+/// are undefined.
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_insert_si64(__m128i __x, __m128i __y)
{
return (__m128i)__builtin_ia32_insertq((__v2di)__x, (__v2di)__y);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+/// \brief Stores a 64-bit double-precision value in a 64-bit memory location.
+/// To minimize caching, the data is flagged as non-temporal (unlikely to be
+/// used again soon).
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// This intrinsic corresponds to the \c MOVNTSD instruction.
+/// \endcode
+///
+/// \param __p
+/// The 64-bit memory location used to store the register value.
+/// \param __a
+/// The 64-bit double-precision floating-point register value to
+/// be stored.
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_sd(double *__p, __m128d __a)
{
__builtin_ia32_movntsd(__p, (__v2df)__a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+/// \brief Stores a 32-bit single-precision floating-point value in a 32-bit
+/// memory location. To minimize caching, the data is flagged as
+/// non-temporal (unlikely to be used again soon).
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// This intrinsic corresponds to the \c MOVNTSS instruction.
+/// \endcode
+///
+/// \param __p
+/// The 32-bit memory location used to store the register value.
+/// \param __a
+/// The 32-bit single-precision floating-point register value to
+/// be stored.
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_ss(float *__p, __m128 __a)
{
__builtin_ia32_movntss(__p, (__v4sf)__a);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __SSE4A__ */
#endif /* __AMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/arm_acle.h b/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
index 814df2c..73a7e76 100644
--- a/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
+++ b/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
@@ -45,23 +45,23 @@ extern "C" {
/* 8.4 Hints */
#if !defined(_MSC_VER)
-static __inline__ void __attribute__((always_inline, nodebug)) __wfi(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __wfi(void) {
__builtin_arm_wfi();
}
-static __inline__ void __attribute__((always_inline, nodebug)) __wfe(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __wfe(void) {
__builtin_arm_wfe();
}
-static __inline__ void __attribute__((always_inline, nodebug)) __sev(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __sev(void) {
__builtin_arm_sev();
}
-static __inline__ void __attribute__((always_inline, nodebug)) __sevl(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __sevl(void) {
__builtin_arm_sevl();
}
-static __inline__ void __attribute__((always_inline, nodebug)) __yield(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __yield(void) {
__builtin_arm_yield();
}
#endif
@@ -71,7 +71,7 @@ static __inline__ void __attribute__((always_inline, nodebug)) __yield(void) {
#endif
/* 8.5 Swap */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__swp(uint32_t x, volatile uint32_t *p) {
uint32_t v;
do v = __builtin_arm_ldrex(p); while (__builtin_arm_strex(x, p));
@@ -102,28 +102,28 @@ static __inline__ uint32_t __attribute__((always_inline, nodebug))
#endif
/* 8.7 NOP */
-static __inline__ void __attribute__((always_inline, nodebug)) __nop(void) {
+static __inline__ void __attribute__((__always_inline__, __nodebug__)) __nop(void) {
__builtin_arm_nop();
}
/* 9 DATA-PROCESSING INTRINSICS */
/* 9.2 Miscellaneous data-processing intrinsics */
/* ROR */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__ror(uint32_t x, uint32_t y) {
y %= 32;
if (y == 0) return x;
return (x >> y) | (x << (32 - y));
}
-static __inline__ uint64_t __attribute__((always_inline, nodebug))
+static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__rorll(uint64_t x, uint32_t y) {
y %= 64;
if (y == 0) return x;
return (x >> y) | (x << (64 - y));
}
-static __inline__ unsigned long __attribute__((always_inline, nodebug))
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
__rorl(unsigned long x, uint32_t y) {
#if __SIZEOF_LONG__ == 4
return __ror(x, y);
@@ -134,28 +134,28 @@ static __inline__ unsigned long __attribute__((always_inline, nodebug))
/* CLZ */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__clz(uint32_t t) {
return __builtin_clz(t);
}
-static __inline__ unsigned long __attribute__((always_inline, nodebug))
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
__clzl(unsigned long t) {
return __builtin_clzl(t);
}
-static __inline__ uint64_t __attribute__((always_inline, nodebug))
+static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__clzll(uint64_t t) {
return __builtin_clzll(t);
}
/* REV */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__rev(uint32_t t) {
return __builtin_bswap32(t);
}
-static __inline__ unsigned long __attribute__((always_inline, nodebug))
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
__revl(unsigned long t) {
#if __SIZEOF_LONG__ == 4
return __builtin_bswap32(t);
@@ -164,40 +164,40 @@ static __inline__ unsigned long __attribute__((always_inline, nodebug))
#endif
}
-static __inline__ uint64_t __attribute__((always_inline, nodebug))
+static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__revll(uint64_t t) {
return __builtin_bswap64(t);
}
/* REV16 */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__rev16(uint32_t t) {
return __ror(__rev(t), 16);
}
-static __inline__ unsigned long __attribute__((always_inline, nodebug))
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
__rev16l(unsigned long t) {
return __rorl(__revl(t), sizeof(long) / 2);
}
-static __inline__ uint64_t __attribute__((always_inline, nodebug))
+static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__rev16ll(uint64_t t) {
return __rorll(__revll(t), 32);
}
/* REVSH */
-static __inline__ int16_t __attribute__((always_inline, nodebug))
+static __inline__ int16_t __attribute__((__always_inline__, __nodebug__))
__revsh(int16_t t) {
return __builtin_bswap16(t);
}
/* RBIT */
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__rbit(uint32_t t) {
return __builtin_arm_rbit(t);
}
-static __inline__ uint64_t __attribute__((always_inline, nodebug))
+static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__rbitll(uint64_t t) {
#if __ARM_32BIT_STATE
return (((uint64_t) __builtin_arm_rbit(t)) << 32) |
@@ -207,7 +207,7 @@ static __inline__ uint64_t __attribute__((always_inline, nodebug))
#endif
}
-static __inline__ unsigned long __attribute__((always_inline, nodebug))
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
__rbitl(unsigned long t) {
#if __SIZEOF_LONG__ == 4
return __rbit(t);
@@ -230,17 +230,17 @@ static __inline__ unsigned long __attribute__((always_inline, nodebug))
/* 9.4.2 Saturating addition and subtraction intrinsics */
#if __ARM_32BIT_STATE
-static __inline__ int32_t __attribute__((always_inline, nodebug))
+static __inline__ int32_t __attribute__((__always_inline__, __nodebug__))
__qadd(int32_t t, int32_t v) {
return __builtin_arm_qadd(t, v);
}
-static __inline__ int32_t __attribute__((always_inline, nodebug))
+static __inline__ int32_t __attribute__((__always_inline__, __nodebug__))
__qsub(int32_t t, int32_t v) {
return __builtin_arm_qsub(t, v);
}
-static __inline__ int32_t __attribute__((always_inline, nodebug))
+static __inline__ int32_t __attribute__((__always_inline__, __nodebug__))
__qdbl(int32_t t) {
return __builtin_arm_qadd(t, t);
}
@@ -248,47 +248,55 @@ __qdbl(int32_t t) {
/* 9.7 CRC32 intrinsics */
#if __ARM_FEATURE_CRC32
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32b(uint32_t a, uint8_t b) {
return __builtin_arm_crc32b(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32h(uint32_t a, uint16_t b) {
return __builtin_arm_crc32h(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32w(uint32_t a, uint32_t b) {
return __builtin_arm_crc32w(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32d(uint32_t a, uint64_t b) {
return __builtin_arm_crc32d(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32cb(uint32_t a, uint8_t b) {
return __builtin_arm_crc32cb(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32ch(uint32_t a, uint16_t b) {
return __builtin_arm_crc32ch(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32cw(uint32_t a, uint32_t b) {
return __builtin_arm_crc32cw(a, b);
}
-static __inline__ uint32_t __attribute__((always_inline, nodebug))
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__crc32cd(uint32_t a, uint64_t b) {
return __builtin_arm_crc32cd(a, b);
}
#endif
+/* 10.1 Special register intrinsics */
+#define __arm_rsr(sysreg) __builtin_arm_rsr(sysreg)
+#define __arm_rsr64(sysreg) __builtin_arm_rsr64(sysreg)
+#define __arm_rsrp(sysreg) __builtin_arm_rsrp(sysreg)
+#define __arm_wsr(sysreg, v) __builtin_arm_wsr(sysreg, v)
+#define __arm_wsr64(sysreg, v) __builtin_arm_wsr64(sysreg, v)
+#define __arm_wsrp(sysreg, v) __builtin_arm_wsrp(sysreg, v)
+
#if defined(__cplusplus)
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
index 394fdfe..d8b6b0a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
@@ -28,94 +28,97 @@
#ifndef __AVX2INTRIN_H
#define __AVX2INTRIN_H
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* SSE4 Multiple Packed Sums of Absolute Difference. */
#define _mm256_mpsadbw_epu8(X, Y, M) __builtin_ia32_mpsadbw256((X), (Y), (M))
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_abs_epi8(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsb256((__v32qi)__a);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_abs_epi16(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsw256((__v16hi)__a);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_abs_epi32(__m256i __a)
{
return (__m256i)__builtin_ia32_pabsd256((__v8si)__a);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_packs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packsswb256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_packs_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packssdw256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_packus_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_packuswb256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_packus_epi32(__m256i __V1, __m256i __V2)
{
return (__m256i) __builtin_ia32_packusdw256((__v8si)__V1, (__v8si)__V2);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_add_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qi)__a + (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_add_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a + (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_add_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a + (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_add_epi64(__m256i __a, __m256i __b)
{
return __a + __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_adds_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_adds_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_adds_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddusb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_adds_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_paddusw256((__v16hi)__a, (__v16hi)__b);
@@ -126,31 +129,31 @@ _mm256_adds_epu16(__m256i __a, __m256i __b)
__m256i __b = (b); \
(__m256i)__builtin_ia32_palignr256((__v32qi)__a, (__v32qi)__b, (n)); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_and_si256(__m256i __a, __m256i __b)
{
return __a & __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_andnot_si256(__m256i __a, __m256i __b)
{
return ~__a & __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_avg_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pavgb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_avg_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pavgw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M)
{
return (__m256i)__builtin_ia32_pblendvb256((__v32qi)__V1, (__v32qi)__V2,
@@ -160,7 +163,7 @@ _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M)
#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- (__m256d)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
+ (__m256i)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
(((M) & 0x01) ? 16 : 0), \
(((M) & 0x02) ? 17 : 1), \
(((M) & 0x04) ? 18 : 2), \
@@ -178,307 +181,307 @@ _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M)
(((M) & 0x40) ? 30 : 14), \
(((M) & 0x80) ? 31 : 15)); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qi)__a == (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a == (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a == (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi64(__m256i __a, __m256i __b)
{
return (__m256i)(__a == __b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpgt_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qi)__a > (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpgt_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a > (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpgt_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a > (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpgt_epi64(__m256i __a, __m256i __b)
{
return (__m256i)(__a > __b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hadd_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hadd_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hadds_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phaddsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hsub_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hsub_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_hsubs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_phsubsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maddubs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaddubsw256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_madd_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaddwd256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxsd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxub256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxuw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_max_epu32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmaxud256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminsd256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminub256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminuw256 ((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_min_epu32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pminud256((__v8si)__a, (__v8si)__b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm256_movemask_epi8(__m256i __a)
{
return __builtin_ia32_pmovmskb256((__v32qi)__a);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi8_epi16(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxbw256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi8_epi32(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxbd256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi8_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxbq256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi16_epi32(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxwd256((__v8hi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi16_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxwq256((__v8hi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepi32_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovsxdq256((__v4si)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu8_epi16(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxbw256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu8_epi32(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxbd256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu8_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxbq256((__v16qi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu16_epi32(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxwd256((__v8hi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu16_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxwq256((__v8hi)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cvtepu32_epi64(__m128i __V)
{
return (__m256i)__builtin_ia32_pmovzxdq256((__v4si)__V);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mul_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mulhrs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhrsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mulhi_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhuw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mulhi_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pmulhw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mullo_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a * (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mullo_epi32 (__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a * (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mul_epu32(__m256i __a, __m256i __b)
{
return __builtin_ia32_pmuludq256((__v8si)__a, (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_or_si256(__m256i __a, __m256i __b)
{
return __a | __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sad_epu8(__m256i __a, __m256i __b)
{
return __builtin_ia32_psadbw256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_shuffle_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_pshufb256((__v32qi)__a, (__v32qi)__b);
@@ -520,19 +523,19 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b)
8 + (((imm) & 0xc0) >> 6), \
12, 13, 14, 15); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sign_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sign_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sign_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psignd256((__v8si)__a, (__v8si)__b);
@@ -542,61 +545,63 @@ _mm256_sign_epi32(__m256i __a, __m256i __b)
__m256i __a = (a); \
(__m256i)__builtin_ia32_pslldqi256(__a, (count)*8); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+#define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_slli_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psllwi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sll_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psllw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_slli_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_pslldi256((__v8si)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sll_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_pslld256((__v8si)__a, (__v4si)__count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_slli_epi64(__m256i __a, int __count)
{
return __builtin_ia32_psllqi256(__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sll_epi64(__m256i __a, __m128i __count)
{
return __builtin_ia32_psllq256(__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srai_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrawi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sra_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psraw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srai_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psradi256((__v8si)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sra_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrad256((__v8si)__a, (__v4si)__count);
@@ -606,172 +611,180 @@ _mm256_sra_epi32(__m256i __a, __m128i __count)
__m256i __a = (a); \
(__m256i)__builtin_ia32_psrldqi256(__a, (count)*8); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+#define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srli_epi16(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrlwi256((__v16hi)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srl_epi16(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrlw256((__v16hi)__a, (__v8hi)__count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srli_epi32(__m256i __a, int __count)
{
return (__m256i)__builtin_ia32_psrldi256((__v8si)__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srl_epi32(__m256i __a, __m128i __count)
{
return (__m256i)__builtin_ia32_psrld256((__v8si)__a, (__v4si)__count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srli_epi64(__m256i __a, int __count)
{
return __builtin_ia32_psrlqi256(__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srl_epi64(__m256i __a, __m128i __count)
{
return __builtin_ia32_psrlq256(__a, __count);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sub_epi8(__m256i __a, __m256i __b)
{
return (__m256i)((__v32qi)__a - (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sub_epi16(__m256i __a, __m256i __b)
{
return (__m256i)((__v16hi)__a - (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sub_epi32(__m256i __a, __m256i __b)
{
return (__m256i)((__v8si)__a - (__v8si)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sub_epi64(__m256i __a, __m256i __b)
{
return __a - __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_subs_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubsb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_subs_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubsw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_subs_epu8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubusb256((__v32qi)__a, (__v32qi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_subs_epu16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_psubusw256((__v16hi)__a, (__v16hi)__b);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpackhi_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 8, 32+8, 9, 32+9, 10, 32+10, 11, 32+11, 12, 32+12, 13, 32+13, 14, 32+14, 15, 32+15, 24, 32+24, 25, 32+25, 26, 32+26, 27, 32+27, 28, 32+28, 29, 32+29, 30, 32+30, 31, 32+31);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpackhi_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpackhi_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 2, 8+2, 3, 8+3, 6, 8+6, 7, 8+7);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpackhi_epi64(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector(__a, __b, 1, 4+1, 3, 4+3);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpacklo_epi8(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 0, 32+0, 1, 32+1, 2, 32+2, 3, 32+3, 4, 32+4, 5, 32+5, 6, 32+6, 7, 32+7, 16, 32+16, 17, 32+17, 18, 32+18, 19, 32+19, 20, 32+20, 21, 32+21, 22, 32+22, 23, 32+23);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpacklo_epi16(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpacklo_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 0, 8+0, 1, 8+1, 4, 8+4, 5, 8+5);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_unpacklo_epi64(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_shufflevector(__a, __b, 0, 4+0, 2, 4+2);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_xor_si256(__m256i __a, __m256i __b)
{
return __a ^ __b;
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_stream_load_si256(__m256i *__V)
{
return (__m256i)__builtin_ia32_movntdqa256((__v4di *)__V);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_broadcastss_ps(__m128 __X)
{
return (__m128)__builtin_ia32_vbroadcastss_ps((__v4sf)__X);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_broadcastsd_pd(__m128d __a)
+{
+ return __builtin_shufflevector(__a, __a, 0, 0);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_broadcastss_ps(__m128 __X)
{
return (__m256)__builtin_ia32_vbroadcastss_ps256((__v4sf)__X);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_broadcastsd_pd(__m128d __X)
{
return (__m256d)__builtin_ia32_vbroadcastsd_pd256((__v2df)__X);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastsi128_si256(__m128i __X)
{
- return (__m256i)__builtin_ia32_vbroadcastsi256(__X);
+ return (__m256i)__builtin_shufflevector(__X, __X, 0, 1, 0, 1);
}
#define _mm_blend_epi32(V1, V2, M) __extension__ ({ \
@@ -796,56 +809,56 @@ _mm256_broadcastsi128_si256(__m128i __X)
(((M) & 0x40) ? 14 : 6), \
(((M) & 0x80) ? 15 : 7)); })
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastb_epi8(__m128i __X)
{
return (__m256i)__builtin_ia32_pbroadcastb256((__v16qi)__X);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastw_epi16(__m128i __X)
{
return (__m256i)__builtin_ia32_pbroadcastw256((__v8hi)__X);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastd_epi32(__m128i __X)
{
return (__m256i)__builtin_ia32_pbroadcastd256((__v4si)__X);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastq_epi64(__m128i __X)
{
return (__m256i)__builtin_ia32_pbroadcastq256(__X);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastb_epi8(__m128i __X)
{
return (__m128i)__builtin_ia32_pbroadcastb128((__v16qi)__X);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastw_epi16(__m128i __X)
{
return (__m128i)__builtin_ia32_pbroadcastw128((__v8hi)__X);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastd_epi32(__m128i __X)
{
return (__m128i)__builtin_ia32_pbroadcastd128((__v4si)__X);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastq_epi64(__m128i __X)
{
return (__m128i)__builtin_ia32_pbroadcastq128(__X);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_permutevar8x32_epi32(__m256i __a, __m256i __b)
{
return (__m256i)__builtin_ia32_permvarsi256((__v8si)__a, (__v8si)__b);
@@ -857,7 +870,7 @@ _mm256_permutevar8x32_epi32(__m256i __a, __m256i __b)
(M) & 0x3, ((M) & 0xc) >> 2, \
((M) & 0x30) >> 4, ((M) & 0xc0) >> 6); })
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_permutevar8x32_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_permvarsf256((__v8sf)__a, (__v8sf)__b);
@@ -874,118 +887,125 @@ _mm256_permutevar8x32_ps(__m256 __a, __m256 __b)
__m256i __V2 = (V2); \
(__m256i)__builtin_ia32_permti256(__V1, __V2, (M)); })
-#define _mm256_extracti128_si256(A, O) __extension__ ({ \
- __m256i __A = (A); \
- (__m128i)__builtin_ia32_extract128i256(__A, (O)); })
-
-#define _mm256_inserti128_si256(V1, V2, O) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m128i __V2 = (V2); \
- (__m256i)__builtin_ia32_insert128i256(__V1, __V2, (O)); })
-
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+#define _mm256_extracti128_si256(V, M) __extension__ ({ \
+ (__m128i)__builtin_shufflevector( \
+ (__v4di)(V), \
+ (__v4di)(_mm256_setzero_si256()), \
+ (((M) & 1) ? 2 : 0), \
+ (((M) & 1) ? 3 : 1) );})
+
+#define _mm256_inserti128_si256(V1, V2, M) __extension__ ({ \
+ (__m256i)__builtin_shufflevector( \
+ (__v4di)(V1), \
+ (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
+ (((M) & 1) ? 0 : 4), \
+ (((M) & 1) ? 1 : 5), \
+ (((M) & 1) ? 4 : 2), \
+ (((M) & 1) ? 5 : 3) );})
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskload_epi32(int const *__X, __m256i __M)
{
return (__m256i)__builtin_ia32_maskloadd256((const __v8si *)__X, (__v8si)__M);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskload_epi64(long long const *__X, __m256i __M)
{
return (__m256i)__builtin_ia32_maskloadq256((const __v4di *)__X, __M);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskload_epi32(int const *__X, __m128i __M)
{
return (__m128i)__builtin_ia32_maskloadd((const __v4si *)__X, (__v4si)__M);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskload_epi64(long long const *__X, __m128i __M)
{
return (__m128i)__builtin_ia32_maskloadq((const __v2di *)__X, (__v2di)__M);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm256_maskstore_epi32(int *__X, __m256i __M, __m256i __Y)
{
__builtin_ia32_maskstored256((__v8si *)__X, (__v8si)__M, (__v8si)__Y);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm256_maskstore_epi64(long long *__X, __m256i __M, __m256i __Y)
{
__builtin_ia32_maskstoreq256((__v4di *)__X, __M, __Y);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_maskstore_epi32(int *__X, __m128i __M, __m128i __Y)
{
__builtin_ia32_maskstored((__v4si *)__X, (__v4si)__M, (__v4si)__Y);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_maskstore_epi64(long long *__X, __m128i __M, __m128i __Y)
{
__builtin_ia32_maskstoreq(( __v2di *)__X, __M, __Y);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sllv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sllv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_sllv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv4di(__X, __Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sllv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv2di(__X, __Y);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srav_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrav8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srav_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrav4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srlv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv8si((__v8si)__X, (__v8si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srlv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv4si((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_srlv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv4di(__X, __Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srlv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv2di(__X, __Y);
@@ -1231,4 +1251,6 @@ _mm_srlv_epi64(__m128i __X, __m128i __Y)
(const __v4di *)__m, (__v4di)__i, \
(__v4di)_mm256_set1_epi64x(-1), (s)); })
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __AVX2INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
index bc4d4ac..9e8297a9 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
@@ -21,40 +21,1230 @@
*
*===-----------------------------------------------------------------------===
*/
+#ifndef __IMMINTRIN_H
+#error "Never use <avx512bwintrin.h> directly; include <immintrin.h> instead."
+#endif
#ifndef __AVX512BWINTRIN_H
#define __AVX512BWINTRIN_H
typedef unsigned int __mmask32;
typedef unsigned long long __mmask64;
-typedef char __v64qi __attribute__ ((vector_size (64)));
+typedef char __v64qi __attribute__ ((__vector_size__ (64)));
typedef short __v32hi __attribute__ ((__vector_size__ (64)));
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline __v64qi __DEFAULT_FN_ATTRS
+_mm512_setzero_qi (void) {
+ return (__v64qi){ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+static __inline __v32hi __DEFAULT_FN_ATTRS
+_mm512_setzero_hi (void) {
+ return (__v32hi){ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
/* Integer compare */
-static __inline__ __mmask64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_cmpeq_epi8_mask(__m512i __a, __m512i __b) {
return (__mmask64)__builtin_ia32_pcmpeqb512_mask((__v64qi)__a, (__v64qi)__b,
(__mmask64)-1);
}
-static __inline__ __mmask64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_mask_cmpeq_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
return (__mmask64)__builtin_ia32_pcmpeqb512_mask((__v64qi)__a, (__v64qi)__b,
__u);
}
-static __inline__ __mmask32 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpeq_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 0,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpeq_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_cmpeq_epi16_mask(__m512i __a, __m512i __b) {
return (__mmask32)__builtin_ia32_pcmpeqw512_mask((__v32hi)__a, (__v32hi)__b,
(__mmask32)-1);
}
-static __inline__ __mmask32 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_mask_cmpeq_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
return (__mmask32)__builtin_ia32_pcmpeqw512_mask((__v32hi)__a, (__v32hi)__b,
__u);
}
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpeq_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 0,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpeq_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epi8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epi16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epi8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_pcmpgtb512_mask((__v64qi)__a, (__v64qi)__b,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_pcmpgtb512_mask((__v64qi)__a, (__v64qi)__b,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 6,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epi16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_pcmpgtw512_mask((__v32hi)__a, (__v32hi)__b,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_pcmpgtw512_mask((__v32hi)__a, (__v32hi)__b,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 6,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmple_epi8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmple_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmple_epi16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmple_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epi8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epi16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epi8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epu8_mask(__m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
+ (__mmask64)-1);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
+ return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epi16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epu16_mask(__m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
+ return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
+ __u);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_add_epi8 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v64qi) __A + (__v64qi) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_add_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_add_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi)
+ _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_sub_epi8 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v64qi) __A - (__v64qi) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_sub_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi)
+ _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_add_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v32hi) __A + (__v32hi) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_add_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_add_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi)
+ _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_sub_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v32hi) __A - (__v32hi) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_sub_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi)
+ _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mullo_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v32hi) __A * (__v32hi) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mullo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mullo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi)
+ _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_blend_epi8 (__mmask64 __U, __m512i __A, __m512i __W)
+{
+ return (__m512i) __builtin_ia32_blendmb_512_mask ((__v64qi) __A,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_blend_epi16 (__mmask32 __U, __m512i __A, __m512i __W)
+{
+ return (__m512i) __builtin_ia32_blendmw_512_mask ((__v32hi) __A,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_abs_epi8 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_abs_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_abs_epi16 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_abs_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_packs_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_packs_epi32 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_packs_epi32 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) __W,
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_packs_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_packs_epi16 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_packs_epi16 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_packus_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_packus_epi32 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_packus_epi32 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v32hi) __W,
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_packus_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_packus_epi16 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_packus_epi16 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_adds_epi8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_adds_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_adds_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_adds_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_adds_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_adds_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_adds_epu8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_adds_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_adds_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_adds_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_adds_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_avg_epu8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_avg_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_avg_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_avg_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_max_epi8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_max_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_max_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_max_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_max_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_max_epu8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_max_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_max_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_max_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_min_epi8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_min_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_min_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_min_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_min_epu8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_min_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_min_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_min_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_shuffle_epi8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_shuffle_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_shuffle_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_subs_epi8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_subs_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_subs_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_subs_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_subs_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_subs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_subs_epu8 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_subs_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_subs_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi (),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_subs_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_subs_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_subs_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask2_permutex2var_epi16 (__m512i __A, __m512i __I,
+ __mmask32 __U, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A,
+ (__v32hi) __I /* idx */ ,
+ (__v32hi) __B,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_permutex2var_epi16 (__m512i __A, __m512i __I, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I /* idx */,
+ (__v32hi) __A,
+ (__v32hi) __B,
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_permutex2var_epi16 (__m512i __A, __mmask32 __U,
+ __m512i __I, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_vpermt2varhi512_mask ((__v32hi) __I /* idx */,
+ (__v32hi) __A,
+ (__v32hi) __B,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_permutex2var_epi16 (__mmask32 __U, __m512i __A,
+ __m512i __I, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_vpermt2varhi512_maskz ((__v32hi) __I
+ /* idx */ ,
+ (__v32hi) __A,
+ (__v32hi) __B,
+ (__mmask32) __U);
+}
+
+#define _mm512_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), \
+ (p), (__mmask64)-1); })
+
+#define _mm512_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), \
+ (p), (__mmask64)(m)); })
+
+#define _mm512_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), \
+ (p), (__mmask64)-1); })
+
+#define _mm512_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), \
+ (p), (__mmask64)(m)); })
+
+#define _mm512_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), \
+ (p), (__mmask32)-1); })
+
+#define _mm512_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), \
+ (p), (__mmask32)(m)); })
+
+#define _mm512_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), \
+ (p), (__mmask32)-1); })
+
+#define _mm512_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), \
+ (p), (__mmask32)(m)); })
+
+
+#undef __DEFAULT_FN_ATTRS
+
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
new file mode 100644
index 0000000..3894b29
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
@@ -0,0 +1,131 @@
+/*===------------- avx512cdintrin.h - AVX512CD intrinsics ------------------===
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+#ifndef __IMMINTRIN_H
+#error "Never use <avx512cdintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512CDINTRIN_H
+#define __AVX512CDINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512cd")))
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_conflict_epi64 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
+ (__v8di) _mm512_setzero_si512 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_conflict_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
+ (__v8di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_conflict_epi64 (__mmask8 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
+ (__v8di) _mm512_setzero_si512 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_conflict_epi32 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
+ (__v16si) _mm512_setzero_si512 (),
+ (__mmask16) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_conflict_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_conflict_epi32 (__mmask16 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
+ (__v16si) _mm512_setzero_si512 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_lzcnt_epi32 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
+ (__v16si) _mm512_setzero_si512 (),
+ (__mmask16) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_lzcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_lzcnt_epi32 (__mmask16 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
+ (__v16si) _mm512_setzero_si512 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_lzcnt_epi64 (__m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
+ (__v8di) _mm512_setzero_si512 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_lzcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
+ (__v8di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A)
+{
+ return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
+ (__v8di) _mm512_setzero_si512 (),
+ (__mmask8) __U);
+}
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
new file mode 100644
index 0000000..c946de2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
@@ -0,0 +1,242 @@
+/*===---- avx512dqintrin.h - AVX512DQ intrinsics ---------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <avx512dqintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512DQINTRIN_H
+#define __AVX512DQINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
+ return (__m512i) ((__v8di) __A * (__v8di) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mullo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_xor_pd (__m512d __A, __m512d __B) {
+ return (__m512d) ((__v8di) __A ^ (__v8di) __B);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_xor_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_xor_pd (__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_xor_ps (__m512 __A, __m512 __B) {
+ return (__m512) ((__v16si) __A ^ (__v16si) __B);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_xor_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_xor_ps (__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_or_pd (__m512d __A, __m512d __B) {
+ return (__m512d) ((__v8di) __A | (__v8di) __B);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_or_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_or_pd (__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_or_ps (__m512 __A, __m512 __B) {
+ return (__m512) ((__v16si) __A | (__v16si) __B);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_or_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_or_ps (__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_and_pd (__m512d __A, __m512d __B) {
+ return (__m512d) ((__v8di) __A & (__v8di) __B);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_and_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_and_pd (__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_and_ps (__m512 __A, __m512 __B) {
+ return (__m512) ((__v16si) __A & (__v16si) __B);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_and_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_and_ps (__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_andnot_pd (__m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_andnot_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_andnot_pd (__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_andnot_ps (__m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) -1);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_andnot_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_andnot_ps (__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
index 1a5ea15..56edffc 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
@@ -27,86 +27,259 @@
#ifndef __AVX512ERINTRIN_H
#define __AVX512ERINTRIN_H
+// exp2a23
+#define _mm512_exp2a23_round_pd(A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm512_mask_exp2a23_round_pd(S, M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_maskz_exp2a23_round_pd(M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_exp2pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_exp2a23_pd(A) \
+ _mm512_exp2a23_round_pd((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_exp2a23_pd(S, M, A) \
+ _mm512_mask_exp2a23_round_pd((S), (M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_exp2a23_pd(M, A) \
+ _mm512_maskz_exp2a23_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_exp2a23_round_ps(A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm512_mask_exp2a23_round_ps(S, M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_maskz_exp2a23_round_ps(M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_exp2ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_exp2a23_ps(A) \
+ _mm512_exp2a23_round_ps((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_exp2a23_ps(S, M, A) \
+ _mm512_mask_exp2a23_round_ps((S), (M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_exp2a23_ps(M, A) \
+ _mm512_maskz_exp2a23_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
// rsqrt28
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
-_mm512_rsqrt28_round_pd (__m512d __A, int __R)
-{
- return (__m512d)__builtin_ia32_rsqrt28pd_mask ((__v8df)__A,
- (__v8df)_mm512_setzero_pd(),
- (__mmask8)-1,
- __R);
-}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
-_mm512_rsqrt28_round_ps(__m512 __A, int __R)
-{
- return (__m512)__builtin_ia32_rsqrt28ps_mask ((__v16sf)__A,
- (__v16sf)_mm512_setzero_ps(),
- (__mmask16)-1,
- __R);
-}
-
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
-_mm_rsqrt28_round_ss(__m128 __A, __m128 __B, int __R)
-{
- return (__m128) __builtin_ia32_rsqrt28ss_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) -1,
- __R);
-}
-
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
-_mm_rsqrt28_round_sd (__m128d __A, __m128d __B, int __R)
-{
- return (__m128d) __builtin_ia32_rsqrt28sd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) -1,
- __R);
-}
+#define _mm512_rsqrt28_round_pd(A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm512_mask_rsqrt28_round_pd(S, M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_maskz_rsqrt28_round_pd(M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rsqrt28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_rsqrt28_pd(A) \
+ _mm512_rsqrt28_round_pd((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_rsqrt28_pd(S, M, A) \
+ _mm512_mask_rsqrt28_round_pd((S), (M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_rsqrt28_pd(M, A) \
+ _mm512_maskz_rsqrt28_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_rsqrt28_round_ps(A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)-1, (R)); })
+
+#define _mm512_mask_rsqrt28_round_ps(S, M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(S), \
+ (__mmask16)(M), (R)); })
+
+#define _mm512_maskz_rsqrt28_round_ps(M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rsqrt28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)(M), (R)); })
+
+#define _mm512_rsqrt28_ps(A) \
+ _mm512_rsqrt28_round_ps((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_rsqrt28_ps(S, M, A) \
+ _mm512_mask_rsqrt28_round_ps((S), (M), A, _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_rsqrt28_ps(M, A) \
+ _mm512_maskz_rsqrt28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_rsqrt28_round_ss(A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm_mask_rsqrt28_round_ss(S, M, A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)(__m128)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_maskz_rsqrt28_round_ss(M, A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_rsqrt28_ss(A, B) \
+ _mm_rsqrt28_round_ss((A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_mask_rsqrt28_ss(S, M, A, B) \
+ _mm_mask_rsqrt28_round_ss((S), (M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_rsqrt28_ss(M, A, B) \
+ _mm_maskz_rsqrt28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+#define _mm_rsqrt28_round_sd(A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm_mask_rsqrt28_round_sd(S, M, A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)(__m128d)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_maskz_rsqrt28_round_sd(M, A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_rsqrt28_sd(A, B) \
+ _mm_rsqrt28_round_sd((A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_mask_rsqrt28_sd(S, M, A, B) \
+ _mm_mask_rsqrt28_round_sd((S), (M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_rsqrt28_sd(M, A, B) \
+ _mm_mask_rsqrt28_round_sd((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
// rcp28
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
-_mm512_rcp28_round_pd (__m512d __A, int __R)
-{
- return (__m512d)__builtin_ia32_rcp28pd_mask ((__v8df)__A,
- (__v8df)_mm512_setzero_pd(),
- (__mmask8)-1,
- __R);
-}
-
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
-_mm512_rcp28_round_ps (__m512 __A, int __R)
-{
- return (__m512)__builtin_ia32_rcp28ps_mask ((__v16sf)__A,
- (__v16sf)_mm512_setzero_ps (),
- (__mmask16)-1,
- __R);
-}
-
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
-_mm_rcp28_round_ss (__m128 __A, __m128 __B, int __R)
-{
- return (__m128) __builtin_ia32_rcp28ss_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) -1,
- __R);
-}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
-_mm_rcp28_round_sd (__m128d __A, __m128d __B, int __R)
-{
- return (__m128d) __builtin_ia32_rcp28sd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) -1,
- __R);
-}
+#define _mm512_rcp28_round_pd(A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm512_mask_rcp28_round_pd(S, M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_maskz_rcp28_round_pd(M, A, R) __extension__ ({ \
+ (__m512d)__builtin_ia32_rcp28pd_mask((__v8df)(__m512d)(A), \
+ (__v8df)_mm512_setzero_pd(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm512_rcp28_pd(A) \
+ _mm512_rcp28_round_pd((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_rcp28_pd(S, M, A) \
+ _mm512_mask_rcp28_round_pd((S), (M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_rcp28_pd(M, A) \
+ _mm512_maskz_rcp28_round_pd((M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_rcp28_round_ps(A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)-1, (R)); })
+
+#define _mm512_mask_rcp28_round_ps(S, M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(S), \
+ (__mmask16)(M), (R)); })
+
+#define _mm512_maskz_rcp28_round_ps(M, A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_rcp28ps_mask((__v16sf)(__m512)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)(M), (R)); })
+
+#define _mm512_rcp28_ps(A) \
+ _mm512_rcp28_round_ps((A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_rcp28_ps(S, M, A) \
+ _mm512_mask_rcp28_round_ps((S), (M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_maskz_rcp28_ps(M, A) \
+ _mm512_maskz_rcp28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_rcp28_round_ss(A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm_mask_rcp28_round_ss(S, M, A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)(__m128)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_maskz_rcp28_round_ss(M, A, B, R) __extension__ ({ \
+ (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_rcp28_ss(A, B) \
+ _mm_rcp28_round_ss((A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_mask_rcp28_ss(S, M, A, B) \
+ _mm_mask_rcp28_round_ss((S), (M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_rcp28_ss(M, A, B) \
+ _mm_maskz_rcp28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_rcp28_round_sd(A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm_mask_rcp28_round_sd(S, M, A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)(__m128d)(S), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_maskz_rcp28_round_sd(M, A, B, R) __extension__ ({ \
+ (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)(M), (R)); })
+
+#define _mm_rcp28_sd(A, B) \
+ _mm_rcp28_round_sd((A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_mask_rcp28_sd(S, M, A, B) \
+ _mm_mask_rcp28_round_sd((S), (M), (A), (B), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_rcp28_sd(M, A, B) \
+ _mm_maskz_rcp28_round_sd((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
#endif // __AVX512ERINTRIN_H
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
index 9c80710..4f7cba0 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
@@ -46,15 +46,18 @@ typedef unsigned short __mmask16;
#define _MM_FROUND_TO_ZERO 0x03
#define _MM_FROUND_CUR_DIRECTION 0x04
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* Create vectors with repeated elements */
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_setzero_si512(void)
{
return (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
{
return (__m512i) __builtin_ia32_pbroadcastd512_gpr_mask (__A,
@@ -63,7 +66,7 @@ _mm512_maskz_set1_epi32(__mmask16 __M, int __A)
__M);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_set1_epi64(__mmask8 __M, long long __A)
{
#ifdef __x86_64__
@@ -79,45 +82,45 @@ _mm512_maskz_set1_epi64(__mmask8 __M, long long __A)
#endif
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_setzero_ps(void)
{
return (__m512){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_setzero_pd(void)
{
return (__m512d){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_set1_ps(float __w)
{
return (__m512){ __w, __w, __w, __w, __w, __w, __w, __w,
__w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_set1_pd(double __w)
{
return (__m512d){ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m512i __attribute__((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_set1_epi32(int __s)
{
return (__m512i)(__v16si){ __s, __s, __s, __s, __s, __s, __s, __s,
__s, __s, __s, __s, __s, __s, __s, __s };
}
-static __inline __m512i __attribute__((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_set1_epi64(long long __d)
{
return (__m512i)(__v8di){ __d, __d, __d, __d, __d, __d, __d, __d };
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_broadcastss_ps(__m128 __X)
{
float __f = __X[0];
@@ -127,7 +130,7 @@ _mm512_broadcastss_ps(__m128 __X)
__f, __f, __f, __f };
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_broadcastsd_pd(__m128d __X)
{
double __d = __X[0];
@@ -137,70 +140,388 @@ _mm512_broadcastsd_pd(__m128d __X)
/* Cast between vector types */
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_castpd256_pd512(__m256d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, -1, -1, -1, -1);
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_castps256_ps512(__m256 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, 4, 5, 6, 7,
-1, -1, -1, -1, -1, -1, -1, -1);
}
-static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline __m128d __DEFAULT_FN_ATTRS
_mm512_castpd512_pd128(__m512d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1);
}
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm512_castps512_ps128(__m512 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3);
}
+/* Bitwise operators */
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_and_epi32(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandd512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_and_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandd512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_and_epi64(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_and_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pandq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_andnot_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_andnot_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_andnot_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_andnot_epi64 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_andnot_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di) __W, __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_andnot_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pandnq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di)
+ _mm512_setzero_pd (),
+ __U);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_or_epi32(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_or_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_or_epi64(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_or_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_porq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_xor_epi32(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si) __src,
+ (__mmask16) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_xor_epi32(__mmask16 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxord512_mask((__v16si) __a,
+ (__v16si) __b,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_xor_epi64(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di) __src,
+ (__mmask8) __k);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_xor_epi64(__mmask8 __k, __m512i __a, __m512i __b)
+{
+ return (__m512i) __builtin_ia32_pxorq512_mask ((__v8di) __a,
+ (__v8di) __b,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __k);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_and_si512(__m512i __a, __m512i __b)
+{
+ return __a & __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_or_si512(__m512i __a, __m512i __b)
+{
+ return __a | __b;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_xor_si512(__m512i __a, __m512i __b)
+{
+ return __a ^ __b;
+}
/* Arithmetic */
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_add_pd(__m512d __a, __m512d __b)
{
return __a + __b;
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_add_ps(__m512 __a, __m512 __b)
{
return __a + __b;
}
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_mul_pd(__m512d __a, __m512d __b)
{
return __a * __b;
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_mul_ps(__m512 __a, __m512 __b)
{
return __a * __b;
}
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_sub_pd(__m512d __a, __m512d __b)
{
return __a - __b;
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_sub_ps(__m512 __a, __m512 __b)
{
return __a - __b;
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_add_epi64 (__m512i __A, __m512i __B)
+{
+ return (__m512i) ((__v8di) __A + (__v8di) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_add_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_add_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_sub_epi64 (__m512i __A, __m512i __B)
+{
+ return (__m512i) ((__v8di) __A - (__v8di) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_sub_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A,
+ (__v8di) __B,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_add_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) ((__v16si) __A + (__v16si) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_add_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_sub_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) ((__v16si) __A - (__v16si) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_sub_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_max_pd(__m512d __A, __m512d __B)
{
return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A,
@@ -211,7 +532,7 @@ _mm512_max_pd(__m512d __A, __m512d __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_max_ps(__m512 __A, __m512 __B)
{
return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A,
@@ -223,7 +544,7 @@ _mm512_max_ps(__m512 __A, __m512 __B)
}
static __inline __m512i
-__attribute__ ((__always_inline__, __nodebug__))
+__DEFAULT_FN_ATTRS
_mm512_max_epi32(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxsd512_mask ((__v16si) __A,
@@ -233,7 +554,7 @@ _mm512_max_epi32(__m512i __A, __m512i __B)
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_max_epu32(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxud512_mask ((__v16si) __A,
@@ -243,7 +564,7 @@ _mm512_max_epu32(__m512i __A, __m512i __B)
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_max_epi64(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxsq512_mask ((__v8di) __A,
@@ -253,7 +574,7 @@ _mm512_max_epi64(__m512i __A, __m512i __B)
(__mmask8) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_max_epu64(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxuq512_mask ((__v8di) __A,
@@ -263,7 +584,7 @@ _mm512_max_epu64(__m512i __A, __m512i __B)
(__mmask8) -1);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_min_pd(__m512d __A, __m512d __B)
{
return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A,
@@ -274,7 +595,7 @@ _mm512_min_pd(__m512d __A, __m512d __B)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_min_ps(__m512 __A, __m512 __B)
{
return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A,
@@ -286,7 +607,7 @@ _mm512_min_ps(__m512 __A, __m512 __B)
}
static __inline __m512i
-__attribute__ ((__always_inline__, __nodebug__))
+__DEFAULT_FN_ATTRS
_mm512_min_epi32(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminsd512_mask ((__v16si) __A,
@@ -296,7 +617,7 @@ _mm512_min_epi32(__m512i __A, __m512i __B)
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_min_epu32(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminud512_mask ((__v16si) __A,
@@ -306,7 +627,7 @@ _mm512_min_epu32(__m512i __A, __m512i __B)
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_min_epi64(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminsq512_mask ((__v8di) __A,
@@ -316,7 +637,7 @@ _mm512_min_epi64(__m512i __A, __m512i __B)
(__mmask8) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_min_epu64(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminuq512_mask ((__v8di) __A,
@@ -326,7 +647,7 @@ _mm512_min_epu64(__m512i __A, __m512i __B)
(__mmask8) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mul_epi32(__m512i __X, __m512i __Y)
{
return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
@@ -336,7 +657,25 @@ _mm512_mul_epi32(__m512i __X, __m512i __Y)
(__mmask8) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mul_epi32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
+{
+ return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
+ (__v16si) __Y,
+ (__v8di) __W, __M);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mul_epi32 (__mmask8 __M, __m512i __X, __m512i __Y)
+{
+ return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
+ (__v16si) __Y,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ __M);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mul_epu32(__m512i __X, __m512i __Y)
{
return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
@@ -346,7 +685,49 @@ _mm512_mul_epu32(__m512i __X, __m512i __Y)
(__mmask8) -1);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mul_epu32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
+{
+ return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
+ (__v16si) __Y,
+ (__v8di) __W, __M);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mul_epu32 (__mmask8 __M, __m512i __X, __m512i __Y)
+{
+ return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
+ (__v16si) __Y,
+ (__v8di)
+ _mm512_setzero_si512 (),
+ __M);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_mullo_epi32 (__m512i __A, __m512i __B)
+{
+ return (__m512i) ((__v16si) __A * (__v16si) __B);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mullo_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __M);
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mullo_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A,
+ (__v16si) __B,
+ (__v16si) __W, __M);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_sqrt_pd(__m512d a)
{
return (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)a,
@@ -355,7 +736,7 @@ _mm512_sqrt_pd(__m512d a)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_sqrt_ps(__m512 a)
{
return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)a,
@@ -364,7 +745,7 @@ _mm512_sqrt_ps(__m512 a)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_rsqrt14_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A,
@@ -372,7 +753,7 @@ _mm512_rsqrt14_pd(__m512d __A)
_mm512_setzero_pd (),
(__mmask8) -1);}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_rsqrt14_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A,
@@ -381,7 +762,7 @@ _mm512_rsqrt14_ps(__m512 __A)
(__mmask16) -1);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rsqrt14_ss(__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A,
@@ -391,7 +772,7 @@ _mm_rsqrt14_ss(__m128 __A, __m128 __B)
(__mmask8) -1);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_rsqrt14_sd(__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __A,
@@ -401,7 +782,7 @@ _mm_rsqrt14_sd(__m128d __A, __m128d __B)
(__mmask8) -1);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_rcp14_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A,
@@ -410,7 +791,7 @@ _mm512_rcp14_pd(__m512d __A)
(__mmask8) -1);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_rcp14_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A,
@@ -418,7 +799,7 @@ _mm512_rcp14_ps(__m512 __A)
_mm512_setzero_ps (),
(__mmask16) -1);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp14_ss(__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A,
@@ -428,7 +809,7 @@ _mm_rcp14_ss(__m128 __A, __m128 __B)
(__mmask8) -1);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_rcp14_sd(__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __A,
@@ -438,7 +819,7 @@ _mm_rcp14_sd(__m128d __A, __m128d __B)
(__mmask8) -1);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_floor_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -447,7 +828,7 @@ _mm512_floor_ps(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_floor_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -456,7 +837,7 @@ _mm512_floor_pd(__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_ceil_ps(__m512 __A)
{
return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A,
@@ -465,7 +846,7 @@ _mm512_ceil_ps(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_ceil_pd(__m512d __A)
{
return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A,
@@ -474,7 +855,7 @@ _mm512_ceil_pd(__m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512i __attribute__ (( __always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi64(__m512i __A)
{
return (__m512i) __builtin_ia32_pabsq512_mask ((__v8di) __A,
@@ -483,7 +864,7 @@ _mm512_abs_epi64(__m512i __A)
(__mmask8) -1);
}
-static __inline __m512i __attribute__ (( __always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi32(__m512i __A)
{
return (__m512i) __builtin_ia32_pabsd512_mask ((__v16si) __A,
@@ -492,90 +873,787 @@ _mm512_abs_epi32(__m512i __A)
(__mmask16) -1);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
-_mm512_roundscale_ps(__m512 __A, const int __imm)
+#define _mm512_roundscale_ps(A, B) __extension__ ({ \
+ (__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(A), (B), (__v16sf)(A), \
+ -1, _MM_FROUND_CUR_DIRECTION); })
+
+#define _mm512_roundscale_pd(A, B) __extension__ ({ \
+ (__m512d)__builtin_ia32_rndscalepd_mask((__v8df)(A), (B), (__v8df)(A), \
+ -1, _MM_FROUND_CUR_DIRECTION); })
+
+#define _mm512_fmadd_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_mask_fmadd_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_mask3_fmadd_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_maskz_fmadd_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_fmsub_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_mask_fmsub_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_maskz_fmsub_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_fnmadd_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_mask3_fnmadd_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask3 (-(__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_maskz_fnmadd_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_fnmsub_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_maskz_fnmsub_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
{
- return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, __imm,
- (__v16sf) __A, -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
-_mm512_roundscale_pd(__m512d __A, const int __imm)
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
{
- return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, __imm,
- (__v8df) __A, -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
-_mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C)
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
{
- return (__m512d)
- __builtin_ia32_vfmaddpd512_mask(__A,
- __B,
- __C,
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C)
{
- return (__m512d)
- __builtin_ia32_vfmsubpd512_mask(__A,
- __B,
- __C,
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C)
{
- return (__m512d)
- __builtin_ia32_vfnmaddpd512_mask(__A,
- __B,
- __C,
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask3 (-(__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_mask (-(__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_fmadd_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_mask_fmadd_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_mask3_fmadd_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_maskz_fmadd_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_fmsub_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_mask_fmsub_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_maskz_fmsub_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_fnmadd_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_mask3_fnmadd_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask3 (-(__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_maskz_fnmadd_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_fnmsub_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_maskz_fnmsub_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C)
{
- return (__m512)
- __builtin_ia32_vfmaddps512_mask(__A,
- __B,
- __C,
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C)
{
- return (__m512)
- __builtin_ia32_vfmsubps512_mask(__A,
- __B,
- __C,
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C)
{
- return (__m512)
- __builtin_ia32_vfnmaddps512_mask(__A,
- __B,
- __C,
- (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_mask3 (-(__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_mask (-(__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_fmaddsub_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_mask_fmaddsub_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_mask3_fmaddsub_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_maskz_fmaddsub_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_fmsubadd_round_pd(A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) -1, (R)); })
+
+
+#define _mm512_mask_fmsubadd_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_maskz_fmsubadd_round_pd(U, A, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) (A), \
+ (__v8df) (B), -(__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
}
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A,
+ (__v8df) __B,
+ -(__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_fmaddsub_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_mask_fmaddsub_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_mask3_fmaddsub_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_maskz_fmaddsub_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_fmsubadd_round_ps(A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) -1, (R)); })
+
+
+#define _mm512_mask_fmsubadd_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_maskz_fmsubadd_round_ps(U, A, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) (A), \
+ (__v16sf) (B), -(__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A,
+ (__v16sf) __B,
+ -(__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask3_fmsub_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmsubpd512_mask3 ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask3_fmsub_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmsubps512_mask3 ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask3_fmsubadd_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask3_fmsubadd_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask_fnmadd_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfnmaddpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask_fnmadd_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfnmaddps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask_fnmsub_round_pd(A, U, B, C, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+#define _mm512_mask3_fnmsub_round_pd(A, B, C, U, R) __extension__ ({ \
+ (__m512d) __builtin_ia32_vfnmsubpd512_mask3 ((__v8df) (A), \
+ (__v8df) (B), (__v8df) (C), \
+ (__mmask8) (U), (R)); })
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C)
+{
+ return (__m512d) __builtin_ia32_vfnmsubpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U)
+{
+ return (__m512d) __builtin_ia32_vfnmsubpd512_mask3 ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __C,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mask_fnmsub_round_ps(A, U, B, C, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+#define _mm512_mask3_fnmsub_round_ps(A, B, C, U, R) __extension__ ({ \
+ (__m512) __builtin_ia32_vfnmsubps512_mask3 ((__v16sf) (A), \
+ (__v16sf) (B), (__v16sf) (C), \
+ (__mmask16) (U), (R)); })
+
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C)
+{
+ return (__m512) __builtin_ia32_vfnmsubps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U)
+{
+ return (__m512) __builtin_ia32_vfnmsubps512_mask3 ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __C,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+
+
/* Vector permutations */
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_permutex2var_epi32(__m512i __A, __m512i __I, __m512i __B)
{
return (__m512i) __builtin_ia32_vpermt2vard512_mask ((__v16si) __I
@@ -584,7 +1662,7 @@ _mm512_permutex2var_epi32(__m512i __A, __m512i __I, __m512i __B)
(__v16si) __B,
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_permutex2var_epi64(__m512i __A, __m512i __I, __m512i __B)
{
return (__m512i) __builtin_ia32_vpermt2varq512_mask ((__v8di) __I
@@ -594,7 +1672,7 @@ _mm512_permutex2var_epi64(__m512i __A, __m512i __I, __m512i __B)
(__mmask8) -1);
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_permutex2var_pd(__m512d __A, __m512i __I, __m512d __B)
{
return (__m512d) __builtin_ia32_vpermt2varpd512_mask ((__v8di) __I
@@ -603,7 +1681,7 @@ _mm512_permutex2var_pd(__m512d __A, __m512i __I, __m512d __B)
(__v8df) __B,
(__mmask8) -1);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_permutex2var_ps(__m512 __A, __m512i __I, __m512 __B)
{
return (__m512) __builtin_ia32_vpermt2varps512_mask ((__v16si) __I
@@ -613,29 +1691,39 @@ _mm512_permutex2var_ps(__m512 __A, __m512i __I, __m512 __B)
(__mmask16) -1);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_valign_epi64(__m512i __A, __m512i __B, const int __I)
-{
- return (__m512i) __builtin_ia32_alignq512_mask((__v8di)__A,
- (__v8di)__B,
- __I,
- (__v8di)_mm512_setzero_si512(),
- (__mmask8) -1);
-}
-
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_valign_epi32(__m512i __A, __m512i __B, const int __I)
-{
- return (__m512i)__builtin_ia32_alignd512_mask((__v16si)__A,
- (__v16si)__B,
- __I,
- (__v16si)_mm512_setzero_si512(),
- (__mmask16) -1);
-}
+#define _mm512_alignr_epi64(A, B, I) __extension__ ({ \
+ (__m512i)__builtin_ia32_alignq512_mask((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), \
+ (I), (__v8di)_mm512_setzero_si512(), \
+ (__mmask8)-1); })
+
+#define _mm512_alignr_epi32(A, B, I) __extension__ ({ \
+ (__m512i)__builtin_ia32_alignd512_mask((__v16si)(__m512i)(A), \
+ (__v16si)(__m512i)(B), \
+ (I), (__v16si)_mm512_setzero_si512(), \
+ (__mmask16)-1); })
+
+/* Vector Extract */
+
+#define _mm512_extractf64x4_pd(A, I) __extension__ ({ \
+ __m512d __A = (A); \
+ (__m256d) \
+ __builtin_ia32_extractf64x4_mask((__v8df)__A, \
+ (I), \
+ (__v4df)_mm256_setzero_si256(), \
+ (__mmask8) -1); })
+
+#define _mm512_extractf32x4_ps(A, I) __extension__ ({ \
+ __m512 __A = (A); \
+ (__m128) \
+ __builtin_ia32_extractf32x4_mask((__v16sf)__A, \
+ (I), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8) -1); })
/* Vector Blend */
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W)
{
return (__m512d) __builtin_ia32_blendmpd_512_mask ((__v8df) __A,
@@ -643,7 +1731,7 @@ _mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W)
(__mmask8) __U);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W)
{
return (__m512) __builtin_ia32_blendmps_512_mask ((__v16sf) __A,
@@ -651,7 +1739,7 @@ _mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W)
(__mmask16) __U);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_blendmq_512_mask ((__v8di) __A,
@@ -659,7 +1747,7 @@ _mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W)
(__mmask8) __U);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_blendmd_512_mask ((__v16si) __A,
@@ -669,26 +1757,41 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
/* Compare */
-static __inline __mmask16 __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cmp_ps_mask(__m512 a, __m512 b, const int p)
-{
- return (__mmask16) __builtin_ia32_cmpps512_mask ((__v16sf) a,
- (__v16sf) b, p, (__mmask16) -1,
- _MM_FROUND_CUR_DIRECTION);
-}
+#define _mm512_cmp_round_ps_mask(A, B, P, R) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpps512_mask((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), \
+ (P), (__mmask16)-1, (R)); })
-static __inline __mmask8 __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cmp_pd_mask(__m512d __X, __m512d __Y, const int __P)
-{
- return (__mmask8) __builtin_ia32_cmppd512_mask ((__v8df) __X,
- (__v8df) __Y, __P,
- (__mmask8) -1,
- _MM_FROUND_CUR_DIRECTION);
-}
+#define _mm512_mask_cmp_round_ps_mask(U, A, B, P, R) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpps512_mask((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), \
+ (P), (__mmask16)(U), (R)); })
+
+#define _mm512_cmp_ps_mask(A, B, P) \
+ _mm512_cmp_round_ps_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_cmp_ps_mask(U, A, B, P) \
+ _mm512_mask_cmp_round_ps_mask((U), (A), (B), (P), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_cmp_round_pd_mask(A, B, P, R) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd512_mask((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), \
+ (P), (__mmask8)-1, (R)); })
+
+#define _mm512_mask_cmp_round_pd_mask(U, A, B, P, R) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd512_mask((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), \
+ (P), (__mmask8)(U), (R)); })
+
+#define _mm512_cmp_pd_mask(A, B, P) \
+ _mm512_cmp_round_pd_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
+
+#define _mm512_mask_cmp_pd_mask(U, A, B, P) \
+ _mm512_mask_cmp_round_pd_mask((U), (A), (B), (P), _MM_FROUND_CUR_DIRECTION)
/* Conversion */
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_cvttps_epu32(__m512 __A)
{
return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A,
@@ -698,27 +1801,17 @@ _mm512_cvttps_epu32(__m512 __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512 __attribute__ (( __always_inline__, __nodebug__))
-_mm512_cvt_roundepi32_ps(__m512i __A, const int __R)
-{
- return (__m512) __builtin_ia32_cvtdq2ps512_mask ((__v16si) __A,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1,
- __R);
-}
+#define _mm512_cvt_roundepi32_ps(A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_cvtdq2ps512_mask((__v16si)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)-1, (R)); })
-static __inline __m512 __attribute__ (( __always_inline__, __nodebug__))
-_mm512_cvt_roundepu32_ps(__m512i __A, const int __R)
-{
- return (__m512) __builtin_ia32_cvtudq2ps512_mask ((__v16si) __A,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1,
- __R);
-}
+#define _mm512_cvt_roundepu32_ps(A, R) __extension__ ({ \
+ (__m512)__builtin_ia32_cvtudq2ps512_mask((__v16si)(A), \
+ (__v16sf)_mm512_setzero_ps(), \
+ (__mmask16)-1, (R)); })
-static __inline __m512d __attribute__ (( __always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepi32_pd(__m256i __A)
{
return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A,
@@ -727,7 +1820,7 @@ _mm512_cvtepi32_pd(__m256i __A)
(__mmask8) -1);
}
-static __inline __m512d __attribute__ (( __always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepu32_pd(__m256i __A)
{
return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A,
@@ -735,27 +1828,18 @@ _mm512_cvtepu32_pd(__m256i __A)
_mm512_setzero_pd (),
(__mmask8) -1);
}
-static __inline __m256 __attribute__ (( __always_inline__, __nodebug__))
-_mm512_cvt_roundpd_ps(__m512d __A, const int __R)
-{
- return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) -1,
- __R);
-}
-static __inline __m256i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvtps_ph(__m512 __A, const int __I)
-{
- return (__m256i) __builtin_ia32_vcvtps2ph512_mask ((__v16sf) __A,
- __I,
- (__v16hi)
- _mm256_setzero_si256 (),
- -1);
-}
+#define _mm512_cvt_roundpd_ps(A, R) __extension__ ({ \
+ (__m256)__builtin_ia32_cvtpd2ps512_mask((__v8df)(A), \
+ (__v8sf)_mm256_setzero_ps(), \
+ (__mmask8)-1, (R)); })
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+#define _mm512_cvtps_ph(A, I) __extension__ ({ \
+ (__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(A), (I), \
+ (__v16hi)_mm256_setzero_si256(), \
+ -1); })
+
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_cvtph_ps(__m256i __A)
{
return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A,
@@ -765,7 +1849,7 @@ _mm512_cvtph_ps(__m256i __A)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m512i __attribute__((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_cvttps_epi32(__m512 a)
{
return (__m512i)
@@ -774,7 +1858,7 @@ _mm512_cvttps_epi32(__m512 a)
(__mmask16) -1, _MM_FROUND_CUR_DIRECTION);
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm512_cvttpd_epi32(__m512d a)
{
return (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df) a,
@@ -783,76 +1867,50 @@ _mm512_cvttpd_epi32(__m512d a)
_MM_FROUND_CUR_DIRECTION);
}
-static __inline __m256i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvtt_roundpd_epi32(__m512d __A, const int __R)
-{
- return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1,
- __R);
-}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvtt_roundps_epi32(__m512 __A, const int __R)
-{
- return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1,
- __R);
-}
+#define _mm512_cvtt_roundpd_epi32(A, R) __extension__ ({ \
+ (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df)(A), \
+ (__v8si)_mm256_setzero_si256(), \
+ (__mmask8)-1, (R)); })
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvt_roundps_epi32(__m512 __A, const int __R)
-{
- return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1,
- __R);
-}
-static __inline __m256i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvt_roundpd_epi32(__m512d __A, const int __R)
-{
- return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1,
- __R);
-}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvt_roundps_epu32(__m512 __A, const int __R)
-{
- return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1,
- __R);
-}
-static __inline __m256i __attribute__ ((__always_inline__, __nodebug__))
-_mm512_cvt_roundpd_epu32(__m512d __A, const int __R)
-{
- return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) -1,
- __R);
-}
+#define _mm512_cvtt_roundps_epi32(A, R) __extension__ ({ \
+ (__m512i)__builtin_ia32_cvttps2dq512_mask((__v16sf)(A), \
+ (__v16si)_mm512_setzero_si512(), \
+ (__mmask16)-1, (R)); })
+
+#define _mm512_cvt_roundps_epi32(A, R) __extension__ ({ \
+ (__m512i)__builtin_ia32_cvtps2dq512_mask((__v16sf)(A), \
+ (__v16si)_mm512_setzero_si512(), \
+ (__mmask16)-1, (R)); })
+
+#define _mm512_cvt_roundpd_epi32(A, R) __extension__ ({ \
+ (__m256i)__builtin_ia32_cvtpd2dq512_mask((__v8df)(A), \
+ (__v8si)_mm256_setzero_si256(), \
+ (__mmask8)-1, (R)); })
+
+#define _mm512_cvt_roundps_epu32(A, R) __extension__ ({ \
+ (__m512i)__builtin_ia32_cvtps2udq512_mask((__v16sf)(A), \
+ (__v16si)_mm512_setzero_si512(), \
+ (__mmask16)-1, (R)); })
+
+#define _mm512_cvt_roundpd_epu32(A, R) __extension__ ({ \
+ (__m256i)__builtin_ia32_cvtpd2udq512_mask((__v8df)(A), \
+ (__v8si)_mm256_setzero_si256(), \
+ (__mmask8) -1, (R)); })
/* Unpack and Interleave */
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_unpackhi_pd(__m512d __a, __m512d __b)
{
return __builtin_shufflevector(__a, __b, 1, 9, 1+2, 9+2, 1+4, 9+4, 1+6, 9+6);
}
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_unpacklo_pd(__m512d __a, __m512d __b)
{
return __builtin_shufflevector(__a, __b, 0, 8, 0+2, 8+2, 0+4, 8+4, 0+6, 8+6);
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_unpackhi_ps(__m512 __a, __m512 __b)
{
return __builtin_shufflevector(__a, __b,
@@ -862,7 +1920,7 @@ _mm512_unpackhi_ps(__m512 __a, __m512 __b)
2+12, 18+12, 3+12, 19+12);
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_unpacklo_ps(__m512 __a, __m512 __b)
{
return __builtin_shufflevector(__a, __b,
@@ -874,7 +1932,7 @@ _mm512_unpacklo_ps(__m512 __a, __m512 __b)
/* Bit Test */
-static __inline __mmask16 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __mmask16 __DEFAULT_FN_ATTRS
_mm512_test_epi32_mask(__m512i __A, __m512i __B)
{
return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A,
@@ -882,7 +1940,7 @@ _mm512_test_epi32_mask(__m512i __A, __m512i __B)
(__mmask16) -1);
}
-static __inline __mmask8 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __mmask8 __DEFAULT_FN_ATTRS
_mm512_test_epi64_mask(__m512i __A, __m512i __B)
{
return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A,
@@ -892,7 +1950,7 @@ _mm512_test_epi64_mask(__m512i __A, __m512i __B)
/* SIMD load ops */
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqusi512_mask ((const __v16si *)__P,
@@ -901,7 +1959,7 @@ _mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512i __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqudi512_mask ((const __v8di *)__P,
@@ -910,7 +1968,7 @@ _mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_loadu_ps(__mmask16 __U, void const *__P)
{
return (__m512) __builtin_ia32_loadups512_mask ((const __v16sf *)__P,
@@ -919,7 +1977,7 @@ _mm512_maskz_loadu_ps(__mmask16 __U, void const *__P)
(__mmask16) __U);
}
-static __inline __m512d __attribute__ ((__always_inline__, __nodebug__))
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_loadu_pd(__mmask8 __U, void const *__P)
{
return (__m512d) __builtin_ia32_loadupd512_mask ((const __v8df *)__P,
@@ -928,80 +1986,129 @@ _mm512_maskz_loadu_pd(__mmask8 __U, void const *__P)
(__mmask8) __U);
}
-static __inline __m512d __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_load_ps(__mmask16 __U, void const *__P)
+{
+ return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *)__P,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+static __inline __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_load_pd(__mmask8 __U, void const *__P)
+{
+ return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *)__P,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_loadu_pd(double const *__p)
{
struct __loadu_pd {
__m512d __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_pd*)__p)->__v;
}
-static __inline __m512 __attribute__((__always_inline__, __nodebug__))
+static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_loadu_ps(float const *__p)
{
struct __loadu_ps {
__m512 __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_ps*)__p)->__v;
}
+static __inline __m512 __DEFAULT_FN_ATTRS
+_mm512_load_ps(double const *__p)
+{
+ return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *)__p,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) -1);
+}
+
+static __inline __m512d __DEFAULT_FN_ATTRS
+_mm512_load_pd(float const *__p)
+{
+ return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *)__p,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) -1);
+}
+
/* SIMD store ops */
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A)
{
__builtin_ia32_storedqudi512_mask ((__v8di *)__P, (__v8di) __A,
(__mmask8) __U);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A)
{
__builtin_ia32_storedqusi512_mask ((__v16si *)__P, (__v16si) __A,
(__mmask16) __U);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_mask_storeu_pd(void *__P, __mmask8 __U, __m512d __A)
{
__builtin_ia32_storeupd512_mask ((__v8df *)__P, (__v8df) __A, (__mmask8) __U);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_storeu_pd(void *__P, __m512d __A)
{
__builtin_ia32_storeupd512_mask((__v8df *)__P, (__v8df)__A, (__mmask8)-1);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_mask_storeu_ps(void *__P, __mmask16 __U, __m512 __A)
{
__builtin_ia32_storeups512_mask ((__v16sf *)__P, (__v16sf) __A,
(__mmask16) __U);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_storeu_ps(void *__P, __m512 __A)
{
__builtin_ia32_storeups512_mask((__v16sf *)__P, (__v16sf)__A, (__mmask16)-1);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
-_mm512_store_ps(void *__P, __m512 __A)
+static __inline void __DEFAULT_FN_ATTRS
+_mm512_mask_store_pd(void *__P, __mmask8 __U, __m512d __A)
{
- *(__m512*)__P = __A;
+ __builtin_ia32_storeapd512_mask ((__v8df *)__P, (__v8df) __A, (__mmask8) __U);
}
-static __inline void __attribute__ ((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm512_store_pd(void *__P, __m512d __A)
{
*(__m512d*)__P = __A;
}
+static __inline void __DEFAULT_FN_ATTRS
+_mm512_mask_store_ps(void *__P, __mmask16 __U, __m512 __A)
+{
+ __builtin_ia32_storeaps512_mask ((__v16sf *)__P, (__v16sf) __A,
+ (__mmask16) __U);
+}
+
+static __inline void __DEFAULT_FN_ATTRS
+_mm512_store_ps(void *__P, __m512 __A)
+{
+ *(__m512*)__P = __A;
+}
+
/* Mask ops */
-static __inline __mmask16 __attribute__ ((__always_inline__, __nodebug__))
+static __inline __mmask16 __DEFAULT_FN_ATTRS
_mm512_knot(__mmask16 __M)
{
return __builtin_ia32_knothi(__M);
@@ -1009,28 +2116,342 @@ _mm512_knot(__mmask16 __M)
/* Integer compare */
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_cmpeq_epi32_mask(__m512i __a, __m512i __b) {
return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
(__mmask16)-1);
}
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_mask_cmpeq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
__u);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpeq_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpeq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm512_mask_cmpeq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
__u);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm512_cmpeq_epi64_mask(__m512i __a, __m512i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
(__mmask8)-1);
}
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpeq_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpeq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epi32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epi64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpge_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpge_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epi32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epi64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpgt_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpgt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmple_epi32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmple_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmple_epi64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmple_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmple_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epi32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epi64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmplt_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmplt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epi32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epu32_mask(__m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epi64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_cmpneq_epu64_mask(__m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
+ __u);
+}
+
+#define _mm512_cmp_epi32_mask(a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)-1); })
+
+#define _mm512_cmp_epu32_mask(a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)-1); })
+
+#define _mm512_cmp_epi64_mask(a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)-1); })
+
+#define _mm512_cmp_epu64_mask(a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)-1); })
+
+#define _mm512_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)(m)); })
+
+#define _mm512_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)(m)); })
+
+#define _mm512_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)(m)); })
+
+#define _mm512_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+ __m512i __a = (a); \
+ __m512i __b = (b); \
+ (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)(m)); })
+
+#undef __DEFAULT_FN_ATTRS
+
#endif // __AVX512FINTRIN_H
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
index 11333f8..74ec175 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
@@ -28,56 +28,1880 @@
#ifndef __AVX512VLBWINTRIN_H
#define __AVX512VLBWINTRIN_H
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* Integer compare */
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_cmpeq_epi8_mask(__m128i __a, __m128i __b) {
return (__mmask16)__builtin_ia32_pcmpeqb128_mask((__v16qi)__a, (__v16qi)__b,
(__mmask16)-1);
}
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_mask_cmpeq_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
return (__mmask16)__builtin_ia32_pcmpeqb128_mask((__v16qi)__a, (__v16qi)__b,
__u);
}
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpeq_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 0,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpeq_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 0,
+ __u);
+}
-static __inline__ __mmask32 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi8_mask(__m256i __a, __m256i __b) {
return (__mmask32)__builtin_ia32_pcmpeqb256_mask((__v32qi)__a, (__v32qi)__b,
(__mmask32)-1);
}
-static __inline__ __mmask32 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_mask_cmpeq_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
return (__mmask32)__builtin_ia32_pcmpeqb256_mask((__v32qi)__a, (__v32qi)__b,
__u);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpeq_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 0,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpeq_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_cmpeq_epi16_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqw128_mask((__v8hi)__a, (__v8hi)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_cmpeq_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqw128_mask((__v8hi)__a, (__v8hi)__b,
__u);
}
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpeq_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpeq_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 0,
+ __u);
+}
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi16_mask(__m256i __a, __m256i __b) {
return (__mmask16)__builtin_ia32_pcmpeqw256_mask((__v16hi)__a, (__v16hi)__b,
(__mmask16)-1);
}
-static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_mask_cmpeq_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
return (__mmask16)__builtin_ia32_pcmpeqw256_mask((__v16hi)__a, (__v16hi)__b,
__u);
}
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpeq_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 0,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpeq_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpge_epi8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpge_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epi8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epi16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epi16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epi8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtb128_mask((__v16qi)__a, (__v16qi)__b,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtb128_mask((__v16qi)__a, (__v16qi)__b,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 6,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epi8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_pcmpgtb256_mask((__v32qi)__a, (__v32qi)__b,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_pcmpgtb256_mask((__v32qi)__a, (__v32qi)__b,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 6,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epi16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtw128_mask((__v8hi)__a, (__v8hi)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtw128_mask((__v8hi)__a, (__v8hi)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epi16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtw256_mask((__v16hi)__a, (__v16hi)__b,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_pcmpgtw256_mask((__v16hi)__a, (__v16hi)__b,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 6,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmple_epi8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmple_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmple_epi8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmple_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epi16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmple_epi16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmple_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmplt_epi8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmplt_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epi8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epi16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epi16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epi8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epu8_mask(__m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
+ return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epi8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epu8_mask(__m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
+ (__mmask32)-1);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
+ return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epi16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epu16_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epi16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epu16_mask(__m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
+ (__mmask16)-1);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
+ return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
+ __u);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_add_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){
+ return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_add_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi)
+ _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_add_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_add_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_sub_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi)
+ _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_sub_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_add_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_add_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi)
+ _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_add_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_add_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_sub_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_sub_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi)
+ _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_sub_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_sub_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mullo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mullo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mullo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mullo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W)
+{
+ return (__m128i) __builtin_ia32_blendmb_128_mask ((__v16qi) __A,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W)
+{
+ return (__m256i) __builtin_ia32_blendmb_256_mask ((__v32qi) __A,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W)
+{
+ return (__m128i) __builtin_ia32_blendmw_128_mask ((__v8hi) __A,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W)
+{
+ return (__m256i) __builtin_ia32_blendmw_256_mask ((__v16hi) __A,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_abs_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
+{
+ return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_abs_epi8 (__mmask16 __U, __m128i __A)
+{
+ return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_abs_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
+{
+ return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A)
+{
+ return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_abs_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
+{
+ return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_abs_epi16 (__mmask8 __U, __m128i __A)
+{
+ return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_abs_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
+{
+ return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_abs_epi16 (__mmask16 __U, __m256i __A)
+{
+ return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_packs_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v8hi) _mm_setzero_si128 (), __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_packs_epi32 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v8hi) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_packs_epi32 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_packs_epi32 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v16hi) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_packs_epi16 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_packs_epi16 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v16qi) __W,
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_packs_epi16 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_packs_epi16 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v32qi) __W,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_packus_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_packus_epi32 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v8hi) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_packus_epi32 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_packus_epi32 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v16hi) __W,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_packus_epi16 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_packus_epi16 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v16qi) __W,
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_packus_epi16 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_packus_epi16 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v32qi) __W,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_adds_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_adds_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_adds_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_adds_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_adds_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_adds_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_adds_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_adds_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_adds_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_adds_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_adds_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_adds_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_adds_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_adds_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_adds_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_adds_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_avg_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_avg_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_avg_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_avg_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_avg_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_avg_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_avg_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_avg_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epi8 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epi16 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epi16 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epi16 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epu8 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epu8 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epu8 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epu16 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epu16 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epu16 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epu16 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epi8 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epi16 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epi16 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epi16 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epu8 (__mmask16 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epu8 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epu8 (__m256i __W, __mmask32 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epu16 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epu16 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epu16 (__mmask16 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epu16 (__m256i __W, __mmask16 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_shuffle_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_shuffle_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_shuffle_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_shuffle_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_subs_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_subs_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_subs_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_subs_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_subs_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_subs_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_subs_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_subs_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_subs_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_subs_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_subs_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_subs_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256 (),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_subs_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_subs_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_subs_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_subs_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256 (),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask2_permutex2var_epi16 (__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A,
+ (__v8hi) __I /* idx */ ,
+ (__v8hi) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask2_permutex2var_epi16 (__m256i __A, __m256i __I,
+ __mmask16 __U, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A,
+ (__v16hi) __I /* idx */ ,
+ (__v16hi) __B,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_permutex2var_epi16 (__m128i __A, __m128i __I, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I/* idx */,
+ (__v8hi) __A,
+ (__v8hi) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_permutex2var_epi16 (__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_vpermt2varhi128_mask ((__v8hi) __I/* idx */,
+ (__v8hi) __A,
+ (__v8hi) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_vpermt2varhi128_maskz ((__v8hi) __I/* idx */,
+ (__v8hi) __A,
+ (__v8hi) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_permutex2var_epi16 (__m256i __A, __m256i __I, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I/* idx */,
+ (__v16hi) __A,
+ (__v16hi) __B,
+ (__mmask16) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_permutex2var_epi16 (__m256i __A, __mmask16 __U,
+ __m256i __I, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_vpermt2varhi256_mask ((__v16hi) __I/* idx */,
+ (__v16hi) __A,
+ (__v16hi) __B,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A,
+ __m256i __I, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_vpermt2varhi256_maskz ((__v16hi) __I/* idx */,
+ (__v16hi) __A,
+ (__v16hi) __B,
+ (__mmask16) __U);
+}
+
+#define _mm_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), \
+ (p), (__mmask16)-1); })
+
+#define _mm_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), \
+ (p), (__mmask16)(m)); })
+
+#define _mm_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), \
+ (p), (__mmask16)-1); })
+
+#define _mm_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), \
+ (p), (__mmask16)(m)); })
+
+#define _mm256_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), \
+ (p), (__mmask32)-1); })
+
+#define _mm256_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), \
+ (p), (__mmask32)(m)); })
+
+#define _mm256_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), \
+ (p), (__mmask32)-1); })
+
+#define _mm256_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), \
+ (p), (__mmask32)(m)); })
+
+#define _mm_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), \
+ (p), (__mmask16)-1); })
+
+#define _mm256_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), \
+ (p), (__mmask16)(m)); })
+
+#define _mm256_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), \
+ (p), (__mmask16)-1); })
+
+#define _mm256_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), \
+ (p), (__mmask16)(m)); })
+
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __AVX512VLBWINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
new file mode 100644
index 0000000..1edf29d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
@@ -0,0 +1,353 @@
+/*===---- avx512vldqintrin.h - AVX512VL and AVX512DQ intrinsics ---------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <avx512vldqintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512VLDQINTRIN_H
+#define __AVX512VLDQINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mullo_epi64 (__m256i __A, __m256i __B) {
+ return (__m256i) ((__v4di) __A * (__v4di) __B);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mullo_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mullo_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mullo_epi64 (__m128i __A, __m128i __B) {
+ return (__m128i) ((__v2di) __A * (__v2di) __B);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mullo_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mullo_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_andnot_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_andnot_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_andnot_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_andnot_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_andnot_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_andnot_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_andnot_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_andnot_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_and_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_and_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_and_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_and_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_and_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_and_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_and_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_and_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_xor_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_xor_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_xor_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_xor_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_xor_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_xor_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_xor_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_or_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_or_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_or_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_or_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_or_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_or_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_or_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_or_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
index 8a374b1..fc1b9d6 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
@@ -28,56 +28,1955 @@
#ifndef __AVX512VLINTRIN_H
#define __AVX512VLINTRIN_H
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* Integer compare */
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_cmpeq_epi32_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_cmpeq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
__u);
}
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpeq_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpeq_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 0,
+ __u);
+}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi32_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_cmpeq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
__u);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpeq_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpeq_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 0,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_cmpeq_epi64_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_cmpeq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
__u);
}
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpeq_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpeq_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 0,
+ __u);
+}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_cmpeq_epi64_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_cmpeq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
__u);
}
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpeq_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 0,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpeq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 0,
+ __u);
+}
+
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epi32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epi32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epi64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpge_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpge_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epi64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 5,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpge_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 5,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpge_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 5,
+ __u);
+}
+
+
+
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epi32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epi32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epi64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpgt_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpgt_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epi64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpgt_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 6,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpgt_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 6,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epi32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmple_epi32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmple_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epi64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmple_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmple_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmple_epi64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmple_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 2,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmple_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 2,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epi32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epi32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epi64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmplt_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmplt_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epi64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmplt_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 1,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmplt_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 1,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epi32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epu32_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epi32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epu32_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epi64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_cmpneq_epu64_mask(__m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm_mask_cmpneq_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epi64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 4,
+ __u);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_cmpneq_epu64_mask(__m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 4,
+ (__mmask8)-1);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm256_mask_cmpneq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 4,
+ __u);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_add_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_add_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_add_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_add_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_sub_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_sub_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_add_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_add_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_add_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_add_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_sub_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_sub_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_sub_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_sub_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mul_epi32 (__m256i __W, __mmask8 __M, __m256i __X,
+ __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X,
+ (__v8si) __Y,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mul_epi32 (__mmask8 __M, __m256i __X, __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X,
+ (__v8si) __Y,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mul_epi32 (__m128i __W, __mmask8 __M, __m128i __X,
+ __m128i __Y)
+{
+ return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X,
+ (__v4si) __Y,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y)
+{
+ return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X,
+ (__v4si) __Y,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mul_epu32 (__m256i __W, __mmask8 __M, __m256i __X,
+ __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X,
+ (__v8si) __Y,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mul_epu32 (__mmask8 __M, __m256i __X, __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X,
+ (__v8si) __Y,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mul_epu32 (__m128i __W, __mmask8 __M, __m128i __X,
+ __m128i __Y)
+{
+ return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X,
+ (__v4si) __Y,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mul_epu32 (__mmask8 __M, __m128i __X, __m128i __Y)
+{
+ return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X,
+ (__v4si) __Y,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mullo_epi32 (__mmask8 __M, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mullo_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mullo_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mullo_epi32 (__m128i __W, __mmask16 __M, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_and_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_and_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_and_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_and_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_andnot_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandnd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_andnot_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandnd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_andnot_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandnd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandnd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pord256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_or_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pord256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_or_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pord128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_or_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pord128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_xor_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pxord256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_xor_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pxord256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_xor_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pxord128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_xor_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pxord128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_and_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_and_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_pd (),
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_and_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_and_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_pd (),
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_andnot_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandnq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_andnot_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pandnq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_pd (),
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_andnot_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandnq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_andnot_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pandnq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_pd (),
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_or_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_porq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_or_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_porq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_or_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_porq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_or_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_porq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_xor_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
+ __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pxorq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_xor_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+{
+ return (__m256i) __builtin_ia32_pxorq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_xor_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pxorq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_xor_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+{
+ return (__m128i) __builtin_ia32_pxorq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+#define _mm_cmp_epi32_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)(__m128i)(a), \
+ (__v4si)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)(__m128i)(a), \
+ (__v4si)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm_cmp_epu32_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)(__m128i)(a), \
+ (__v4si)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)(__m128i)(a), \
+ (__v4si)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_epi32_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)(__m256i)(a), \
+ (__v8si)(__m256i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)(__m256i)(a), \
+ (__v8si)(__m256i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_epu32_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)(__m256i)(a), \
+ (__v8si)(__m256i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)(__m256i)(a), \
+ (__v8si)(__m256i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm_cmp_epi64_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)(__m128i)(a), \
+ (__v2di)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)(__m128i)(a), \
+ (__v2di)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm_cmp_epu64_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)(__m128i)(a), \
+ (__v2di)(__m128i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)(__m128i)(a), \
+ (__v2di)(__m128i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_epi64_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)(__m256i)(a), \
+ (__v4di)(__m256i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)(__m256i)(a), \
+ (__v4di)(__m256i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_epu64_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)(__m256i)(a), \
+ (__v4di)(__m256i)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)(__m256i)(a), \
+ (__v4di)(__m256i)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_ps_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpps256_mask((__v8sf)(__m256)(a), \
+ (__v8sf)(__m256)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_ps_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpps256_mask((__v8sf)(__m256)(a), \
+ (__v8sf)(__m256)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm256_cmp_pd_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd256_mask((__v4df)(__m256)(a), \
+ (__v4df)(__m256)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm256_mask_cmp_pd_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd256_mask((__v4df)(__m256)(a), \
+ (__v4df)(__m256)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm128_cmp_ps_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpps128_mask((__v4sf)(__m128)(a), \
+ (__v4sf)(__m128)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm128_mask_cmp_ps_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpps128_mask((__v4sf)(__m128)(a), \
+ (__v4sf)(__m128)(b), \
+ (p), (__mmask8)(m)); })
+
+#define _mm128_cmp_pd_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd128_mask((__v2df)(__m128)(a), \
+ (__v2df)(__m128)(b), \
+ (p), (__mmask8)-1); })
+
+#define _mm128_mask_cmp_pd_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmppd128_mask((__v2df)(__m128)(a), \
+ (__v2df)(__m128)(b), \
+ (p), (__mmask8)(m)); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_mask3 ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_maskz ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_maskz ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_mask3 (-(__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fnmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_maskz (-(__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fnmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddpd128_maskz (-(__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_mask3 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_maskz ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_maskz ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_mask3 (-(__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fnmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_maskz (-(__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fnmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddpd256_maskz (-(__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_mask3 ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_maskz ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_maskz ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_mask3 (-(__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fnmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_maskz (-(__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fnmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddps128_maskz (-(__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_mask3 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_maskz ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_maskz ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_mask3 (-(__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fnmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_maskz (-(__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddps256_maskz (-(__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfmaddsubpd128_mask3 ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddsubpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfmaddsubpd128_maskz ((__v2df) __A,
+ (__v2df) __B,
+ -(__v2df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfmaddsubpd256_mask3 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddsubpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfmaddsubpd256_maskz ((__v4df) __A,
+ (__v4df) __B,
+ -(__v4df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfmaddsubps128_mask3 ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddsubps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfmaddsubps128_maskz ((__v4sf) __A,
+ (__v4sf) __B,
+ -(__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B,
+ __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfmaddsubps256_mask3 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddsubps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfmaddsubps256_maskz ((__v8sf) __A,
+ (__v8sf) __B,
+ -(__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfmsubpd128_mask3 ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfmsubpd256_mask3 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfmsubps128_mask3 ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfmsubps256_mask3 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfmsubaddpd128_mask3 ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfmsubaddpd256_mask3 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfmsubaddps128_mask3 ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfmsubaddps256_mask3 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fnmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfnmaddpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fnmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfnmaddpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fnmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfnmaddps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fnmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfnmaddps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_fnmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C)
+{
+ return (__m128d) __builtin_ia32_vfnmsubpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask3_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U)
+{
+ return (__m128d) __builtin_ia32_vfnmsubpd128_mask3 ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_fnmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C)
+{
+ return (__m256d) __builtin_ia32_vfnmsubpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask3_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U)
+{
+ return (__m256d) __builtin_ia32_vfnmsubpd256_mask3 ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_fnmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C)
+{
+ return (__m128) __builtin_ia32_vfnmsubps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask3_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U)
+{
+ return (__m128) __builtin_ia32_vfnmsubps128_mask3 ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_fnmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C)
+{
+ return (__m256) __builtin_ia32_vfnmsubps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
+{
+ return (__m256) __builtin_ia32_vfnmsubps256_mask3 ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __C,
+ (__mmask8) __U);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __AVX512VLINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
index 4e1044a..c1bc85b 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
@@ -39,110 +39,113 @@ typedef float __m256 __attribute__ ((__vector_size__ (32)));
typedef double __m256d __attribute__((__vector_size__(32)));
typedef long long __m256i __attribute__((__vector_size__(32)));
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* Arithmetic */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_add_pd(__m256d __a, __m256d __b)
{
return __a+__b;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_add_ps(__m256 __a, __m256 __b)
{
return __a+__b;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_sub_pd(__m256d __a, __m256d __b)
{
return __a-__b;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_sub_ps(__m256 __a, __m256 __b)
{
return __a-__b;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_addsub_pd(__m256d __a, __m256d __b)
{
return (__m256d)__builtin_ia32_addsubpd256((__v4df)__a, (__v4df)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_addsub_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_addsubps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_div_pd(__m256d __a, __m256d __b)
{
return __a / __b;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_div_ps(__m256 __a, __m256 __b)
{
return __a / __b;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_max_pd(__m256d __a, __m256d __b)
{
return (__m256d)__builtin_ia32_maxpd256((__v4df)__a, (__v4df)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_max_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_maxps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_min_pd(__m256d __a, __m256d __b)
{
return (__m256d)__builtin_ia32_minpd256((__v4df)__a, (__v4df)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_min_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_minps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_mul_pd(__m256d __a, __m256d __b)
{
return __a * __b;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_mul_ps(__m256 __a, __m256 __b)
{
return __a * __b;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_sqrt_pd(__m256d __a)
{
return (__m256d)__builtin_ia32_sqrtpd256((__v4df)__a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_sqrt_ps(__m256 __a)
{
return (__m256)__builtin_ia32_sqrtps256((__v8sf)__a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_rsqrt_ps(__m256 __a)
{
return (__m256)__builtin_ia32_rsqrtps256((__v8sf)__a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_rcp_ps(__m256 __a)
{
return (__m256)__builtin_ia32_rcpps256((__v8sf)__a);
@@ -162,103 +165,102 @@ _mm256_rcp_ps(__m256 __a)
#define _mm256_floor_ps(V) _mm256_round_ps((V), _MM_FROUND_FLOOR)
/* Logical */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_and_pd(__m256d __a, __m256d __b)
{
return (__m256d)((__v4di)__a & (__v4di)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_and_ps(__m256 __a, __m256 __b)
{
return (__m256)((__v8si)__a & (__v8si)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_andnot_pd(__m256d __a, __m256d __b)
{
return (__m256d)(~(__v4di)__a & (__v4di)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_andnot_ps(__m256 __a, __m256 __b)
{
return (__m256)(~(__v8si)__a & (__v8si)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_or_pd(__m256d __a, __m256d __b)
{
return (__m256d)((__v4di)__a | (__v4di)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_or_ps(__m256 __a, __m256 __b)
{
return (__m256)((__v8si)__a | (__v8si)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_xor_pd(__m256d __a, __m256d __b)
{
return (__m256d)((__v4di)__a ^ (__v4di)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_xor_ps(__m256 __a, __m256 __b)
{
return (__m256)((__v8si)__a ^ (__v8si)__b);
}
/* Horizontal arithmetic */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_hadd_pd(__m256d __a, __m256d __b)
{
return (__m256d)__builtin_ia32_haddpd256((__v4df)__a, (__v4df)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_hadd_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_haddps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_hsub_pd(__m256d __a, __m256d __b)
{
return (__m256d)__builtin_ia32_hsubpd256((__v4df)__a, (__v4df)__b);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_hsub_ps(__m256 __a, __m256 __b)
{
return (__m256)__builtin_ia32_hsubps256((__v8sf)__a, (__v8sf)__b);
}
/* Vector permutations */
-static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline __m128d __DEFAULT_FN_ATTRS
_mm_permutevar_pd(__m128d __a, __m128i __c)
{
return (__m128d)__builtin_ia32_vpermilvarpd((__v2df)__a, (__v2di)__c);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_permutevar_pd(__m256d __a, __m256i __c)
{
return (__m256d)__builtin_ia32_vpermilvarpd256((__v4df)__a, (__v4di)__c);
}
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm_permutevar_ps(__m128 __a, __m128i __c)
{
return (__m128)__builtin_ia32_vpermilvarps((__v4sf)__a, (__v4si)__c);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_permutevar_ps(__m256 __a, __m256i __c)
{
- return (__m256)__builtin_ia32_vpermilvarps256((__v8sf)__a,
- (__v8si)__c);
+ return (__m256)__builtin_ia32_vpermilvarps256((__v8sf)__a, (__v8si)__c);
}
#define _mm_permute_pd(A, C) __extension__ ({ \
@@ -327,14 +329,14 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
(((M) & 0x40) ? 14 : 6), \
(((M) & 0x80) ? 15 : 7)); })
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_blendv_pd(__m256d __a, __m256d __b, __m256d __c)
{
return (__m256d)__builtin_ia32_blendvpd256(
(__v4df)__a, (__v4df)__b, (__v4df)__c);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
{
return (__m256)__builtin_ia32_blendvps256(
@@ -430,42 +432,29 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
__m128 __b = (b); \
(__m128)__builtin_ia32_cmpss((__v4sf)__a, (__v4sf)__b, (c)); })
-/* Vector extract */
-#define _mm256_extractf128_pd(A, O) __extension__ ({ \
- __m256d __A = (A); \
- (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)__A, (O)); })
-
-#define _mm256_extractf128_ps(A, O) __extension__ ({ \
- __m256 __A = (A); \
- (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)__A, (O)); })
-
-#define _mm256_extractf128_si256(A, O) __extension__ ({ \
- __m256i __A = (A); \
- (__m128i)__builtin_ia32_vextractf128_si256((__v8si)__A, (O)); })
-
-static __inline int __attribute__((__always_inline__, __nodebug__))
-_mm256_extract_epi32(__m256i __a, int const __imm)
+static __inline int __DEFAULT_FN_ATTRS
+_mm256_extract_epi32(__m256i __a, const int __imm)
{
__v8si __b = (__v8si)__a;
return __b[__imm & 7];
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
-_mm256_extract_epi16(__m256i __a, int const __imm)
+static __inline int __DEFAULT_FN_ATTRS
+_mm256_extract_epi16(__m256i __a, const int __imm)
{
__v16hi __b = (__v16hi)__a;
return __b[__imm & 15];
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
-_mm256_extract_epi8(__m256i __a, int const __imm)
+static __inline int __DEFAULT_FN_ATTRS
+_mm256_extract_epi8(__m256i __a, const int __imm)
{
__v32qi __b = (__v32qi)__a;
return __b[__imm & 31];
}
#ifdef __x86_64__
-static __inline long long __attribute__((__always_inline__, __nodebug__))
+static __inline long long __DEFAULT_FN_ATTRS
_mm256_extract_epi64(__m256i __a, const int __imm)
{
__v4di __b = (__v4di)__a;
@@ -473,23 +462,7 @@ _mm256_extract_epi64(__m256i __a, const int __imm)
}
#endif
-/* Vector insert */
-#define _mm256_insertf128_pd(V1, V2, O) __extension__ ({ \
- __m256d __V1 = (V1); \
- __m128d __V2 = (V2); \
- (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)__V1, (__v2df)__V2, (O)); })
-
-#define _mm256_insertf128_ps(V1, V2, O) __extension__ ({ \
- __m256 __V1 = (V1); \
- __m128 __V2 = (V2); \
- (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)__V1, (__v4sf)__V2, (O)); })
-
-#define _mm256_insertf128_si256(V1, V2, O) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m128i __V2 = (V2); \
- (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)__V1, (__v4si)__V2, (O)); })
-
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_insert_epi32(__m256i __a, int __b, int const __imm)
{
__v8si __c = (__v8si)__a;
@@ -497,7 +470,7 @@ _mm256_insert_epi32(__m256i __a, int __b, int const __imm)
return (__m256i)__c;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_insert_epi16(__m256i __a, int __b, int const __imm)
{
__v16hi __c = (__v16hi)__a;
@@ -505,7 +478,7 @@ _mm256_insert_epi16(__m256i __a, int __b, int const __imm)
return (__m256i)__c;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_insert_epi8(__m256i __a, int __b, int const __imm)
{
__v32qi __c = (__v32qi)__a;
@@ -514,8 +487,8 @@ _mm256_insert_epi8(__m256i __a, int __b, int const __imm)
}
#ifdef __x86_64__
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
-_mm256_insert_epi64(__m256i __a, int __b, int const __imm)
+static __inline __m256i __DEFAULT_FN_ATTRS
+_mm256_insert_epi64(__m256i __a, long long __b, int const __imm)
{
__v4di __c = (__v4di)__a;
__c[__imm & 3] = __b;
@@ -524,448 +497,448 @@ _mm256_insert_epi64(__m256i __a, int __b, int const __imm)
#endif
/* Conversion */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_cvtepi32_pd(__m128i __a)
{
return (__m256d)__builtin_ia32_cvtdq2pd256((__v4si) __a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_cvtepi32_ps(__m256i __a)
{
return (__m256)__builtin_ia32_cvtdq2ps256((__v8si) __a);
}
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm256_cvtpd_ps(__m256d __a)
{
return (__m128)__builtin_ia32_cvtpd2ps256((__v4df) __a);
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_cvtps_epi32(__m256 __a)
{
return (__m256i)__builtin_ia32_cvtps2dq256((__v8sf) __a);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_cvtps_pd(__m128 __a)
{
return (__m256d)__builtin_ia32_cvtps2pd256((__v4sf) __a);
}
-static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline __m128i __DEFAULT_FN_ATTRS
_mm256_cvttpd_epi32(__m256d __a)
{
return (__m128i)__builtin_ia32_cvttpd2dq256((__v4df) __a);
}
-static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline __m128i __DEFAULT_FN_ATTRS
_mm256_cvtpd_epi32(__m256d __a)
{
return (__m128i)__builtin_ia32_cvtpd2dq256((__v4df) __a);
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_cvttps_epi32(__m256 __a)
{
return (__m256i)__builtin_ia32_cvttps2dq256((__v8sf) __a);
}
/* Vector replicate */
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_movehdup_ps(__m256 __a)
{
return __builtin_shufflevector(__a, __a, 1, 1, 3, 3, 5, 5, 7, 7);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_moveldup_ps(__m256 __a)
{
return __builtin_shufflevector(__a, __a, 0, 0, 2, 2, 4, 4, 6, 6);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_movedup_pd(__m256d __a)
{
return __builtin_shufflevector(__a, __a, 0, 0, 2, 2);
}
/* Unpack and Interleave */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_unpackhi_pd(__m256d __a, __m256d __b)
{
return __builtin_shufflevector(__a, __b, 1, 5, 1+2, 5+2);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_unpacklo_pd(__m256d __a, __m256d __b)
{
return __builtin_shufflevector(__a, __b, 0, 4, 0+2, 4+2);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_unpackhi_ps(__m256 __a, __m256 __b)
{
return __builtin_shufflevector(__a, __b, 2, 10, 2+1, 10+1, 6, 14, 6+1, 14+1);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_unpacklo_ps(__m256 __a, __m256 __b)
{
return __builtin_shufflevector(__a, __b, 0, 8, 0+1, 8+1, 4, 12, 4+1, 12+1);
}
/* Bit Test */
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testz_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestzpd((__v2df)__a, (__v2df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testc_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestcpd((__v2df)__a, (__v2df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testnzc_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_vtestnzcpd((__v2df)__a, (__v2df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testz_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestzps((__v4sf)__a, (__v4sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testc_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestcps((__v4sf)__a, (__v4sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm_testnzc_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_vtestnzcps((__v4sf)__a, (__v4sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testz_pd(__m256d __a, __m256d __b)
{
return __builtin_ia32_vtestzpd256((__v4df)__a, (__v4df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testc_pd(__m256d __a, __m256d __b)
{
return __builtin_ia32_vtestcpd256((__v4df)__a, (__v4df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testnzc_pd(__m256d __a, __m256d __b)
{
return __builtin_ia32_vtestnzcpd256((__v4df)__a, (__v4df)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testz_ps(__m256 __a, __m256 __b)
{
return __builtin_ia32_vtestzps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testc_ps(__m256 __a, __m256 __b)
{
return __builtin_ia32_vtestcps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testnzc_ps(__m256 __a, __m256 __b)
{
return __builtin_ia32_vtestnzcps256((__v8sf)__a, (__v8sf)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testz_si256(__m256i __a, __m256i __b)
{
return __builtin_ia32_ptestz256((__v4di)__a, (__v4di)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testc_si256(__m256i __a, __m256i __b)
{
return __builtin_ia32_ptestc256((__v4di)__a, (__v4di)__b);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_testnzc_si256(__m256i __a, __m256i __b)
{
return __builtin_ia32_ptestnzc256((__v4di)__a, (__v4di)__b);
}
/* Vector extract sign mask */
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_movemask_pd(__m256d __a)
{
return __builtin_ia32_movmskpd256((__v4df)__a);
}
-static __inline int __attribute__((__always_inline__, __nodebug__))
+static __inline int __DEFAULT_FN_ATTRS
_mm256_movemask_ps(__m256 __a)
{
return __builtin_ia32_movmskps256((__v8sf)__a);
}
/* Vector __zero */
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_zeroall(void)
{
__builtin_ia32_vzeroall();
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_zeroupper(void)
{
__builtin_ia32_vzeroupper();
}
/* Vector load with broadcast */
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm_broadcast_ss(float const *__a)
{
float __f = *__a;
return (__m128)(__v4sf){ __f, __f, __f, __f };
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_sd(double const *__a)
{
double __d = *__a;
return (__m256d)(__v4df){ __d, __d, __d, __d };
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ss(float const *__a)
{
float __f = *__a;
return (__m256)(__v8sf){ __f, __f, __f, __f, __f, __f, __f, __f };
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_pd(__m128d const *__a)
{
return (__m256d)__builtin_ia32_vbroadcastf128_pd256(__a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ps(__m128 const *__a)
{
return (__m256)__builtin_ia32_vbroadcastf128_ps256(__a);
}
/* SIMD load ops */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_load_pd(double const *__p)
{
return *(__m256d *)__p;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_load_ps(float const *__p)
{
return *(__m256 *)__p;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_loadu_pd(double const *__p)
{
struct __loadu_pd {
__m256d __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_pd*)__p)->__v;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_loadu_ps(float const *__p)
{
struct __loadu_ps {
__m256 __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_ps*)__p)->__v;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_load_si256(__m256i const *__p)
{
return *__p;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_loadu_si256(__m256i const *__p)
{
struct __loadu_si256 {
__m256i __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_si256*)__p)->__v;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_lddqu_si256(__m256i const *__p)
{
return (__m256i)__builtin_ia32_lddqu256((char const *)__p);
}
/* SIMD store ops */
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_store_pd(double *__p, __m256d __a)
{
*(__m256d *)__p = __a;
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_store_ps(float *__p, __m256 __a)
{
*(__m256 *)__p = __a;
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_pd(double *__p, __m256d __a)
{
__builtin_ia32_storeupd256(__p, (__v4df)__a);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_ps(float *__p, __m256 __a)
{
__builtin_ia32_storeups256(__p, (__v8sf)__a);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_store_si256(__m256i *__p, __m256i __a)
{
*__p = __a;
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_si256(__m256i *__p, __m256i __a)
{
__builtin_ia32_storedqu256((char *)__p, (__v32qi)__a);
}
/* Conditional load ops */
-static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline __m128d __DEFAULT_FN_ATTRS
_mm_maskload_pd(double const *__p, __m128d __m)
{
return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)__p, (__v2df)__m);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_maskload_pd(double const *__p, __m256d __m)
{
return (__m256d)__builtin_ia32_maskloadpd256((const __v4df *)__p,
(__v4df)__m);
}
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm_maskload_ps(float const *__p, __m128 __m)
{
return (__m128)__builtin_ia32_maskloadps((const __v4sf *)__p, (__v4sf)__m);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_maskload_ps(float const *__p, __m256 __m)
{
return (__m256)__builtin_ia32_maskloadps256((const __v8sf *)__p, (__v8sf)__m);
}
/* Conditional store ops */
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_maskstore_ps(float *__p, __m256 __m, __m256 __a)
{
__builtin_ia32_maskstoreps256((__v8sf *)__p, (__v8sf)__m, (__v8sf)__a);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm_maskstore_pd(double *__p, __m128d __m, __m128d __a)
{
__builtin_ia32_maskstorepd((__v2df *)__p, (__v2df)__m, (__v2df)__a);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_maskstore_pd(double *__p, __m256d __m, __m256d __a)
{
__builtin_ia32_maskstorepd256((__v4df *)__p, (__v4df)__m, (__v4df)__a);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm_maskstore_ps(float *__p, __m128 __m, __m128 __a)
{
__builtin_ia32_maskstoreps((__v4sf *)__p, (__v4sf)__m, (__v4sf)__a);
}
/* Cacheability support ops */
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_si256(__m256i *__a, __m256i __b)
{
__builtin_ia32_movntdq256((__v4di *)__a, (__v4di)__b);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_pd(double *__a, __m256d __b)
{
__builtin_ia32_movntpd256(__a, (__v4df)__b);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_ps(float *__p, __m256 __a)
{
__builtin_ia32_movntps256(__p, (__v8sf)__a);
}
/* Create vectors */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set_pd(double __a, double __b, double __c, double __d)
{
return (__m256d){ __d, __c, __b, __a };
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_set_ps(float __a, float __b, float __c, float __d,
- float __e, float __f, float __g, float __h)
+ float __e, float __f, float __g, float __h)
{
return (__m256){ __h, __g, __f, __e, __d, __c, __b, __a };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi32(int __i0, int __i1, int __i2, int __i3,
- int __i4, int __i5, int __i6, int __i7)
+ int __i4, int __i5, int __i6, int __i7)
{
return (__m256i)(__v8si){ __i7, __i6, __i5, __i4, __i3, __i2, __i1, __i0 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi16(short __w15, short __w14, short __w13, short __w12,
- short __w11, short __w10, short __w09, short __w08,
- short __w07, short __w06, short __w05, short __w04,
- short __w03, short __w02, short __w01, short __w00)
+ short __w11, short __w10, short __w09, short __w08,
+ short __w07, short __w06, short __w05, short __w04,
+ short __w03, short __w02, short __w01, short __w00)
{
return (__m256i)(__v16hi){ __w00, __w01, __w02, __w03, __w04, __w05, __w06,
__w07, __w08, __w09, __w10, __w11, __w12, __w13, __w14, __w15 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
- char __b27, char __b26, char __b25, char __b24,
- char __b23, char __b22, char __b21, char __b20,
- char __b19, char __b18, char __b17, char __b16,
- char __b15, char __b14, char __b13, char __b12,
- char __b11, char __b10, char __b09, char __b08,
- char __b07, char __b06, char __b05, char __b04,
- char __b03, char __b02, char __b01, char __b00)
+ char __b27, char __b26, char __b25, char __b24,
+ char __b23, char __b22, char __b21, char __b20,
+ char __b19, char __b18, char __b17, char __b16,
+ char __b15, char __b14, char __b13, char __b12,
+ char __b11, char __b10, char __b09, char __b08,
+ char __b07, char __b06, char __b05, char __b04,
+ char __b03, char __b02, char __b01, char __b00)
{
return (__m256i)(__v32qi){
__b00, __b01, __b02, __b03, __b04, __b05, __b06, __b07,
@@ -975,93 +948,93 @@ _mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
};
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi64x(long long __a, long long __b, long long __c, long long __d)
{
return (__m256i)(__v4di){ __d, __c, __b, __a };
}
/* Create vectors with elements in reverse order */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setr_pd(double __a, double __b, double __c, double __d)
{
return (__m256d){ __a, __b, __c, __d };
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setr_ps(float __a, float __b, float __c, float __d,
- float __e, float __f, float __g, float __h)
+ float __e, float __f, float __g, float __h)
{
return (__m256){ __a, __b, __c, __d, __e, __f, __g, __h };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi32(int __i0, int __i1, int __i2, int __i3,
- int __i4, int __i5, int __i6, int __i7)
+ int __i4, int __i5, int __i6, int __i7)
{
return (__m256i)(__v8si){ __i0, __i1, __i2, __i3, __i4, __i5, __i6, __i7 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi16(short __w15, short __w14, short __w13, short __w12,
- short __w11, short __w10, short __w09, short __w08,
- short __w07, short __w06, short __w05, short __w04,
- short __w03, short __w02, short __w01, short __w00)
+ short __w11, short __w10, short __w09, short __w08,
+ short __w07, short __w06, short __w05, short __w04,
+ short __w03, short __w02, short __w01, short __w00)
{
return (__m256i)(__v16hi){ __w15, __w14, __w13, __w12, __w11, __w10, __w09,
__w08, __w07, __w06, __w05, __w04, __w03, __w02, __w01, __w00 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi8(char __b31, char __b30, char __b29, char __b28,
- char __b27, char __b26, char __b25, char __b24,
- char __b23, char __b22, char __b21, char __b20,
- char __b19, char __b18, char __b17, char __b16,
- char __b15, char __b14, char __b13, char __b12,
- char __b11, char __b10, char __b09, char __b08,
- char __b07, char __b06, char __b05, char __b04,
- char __b03, char __b02, char __b01, char __b00)
+ char __b27, char __b26, char __b25, char __b24,
+ char __b23, char __b22, char __b21, char __b20,
+ char __b19, char __b18, char __b17, char __b16,
+ char __b15, char __b14, char __b13, char __b12,
+ char __b11, char __b10, char __b09, char __b08,
+ char __b07, char __b06, char __b05, char __b04,
+ char __b03, char __b02, char __b01, char __b00)
{
return (__m256i)(__v32qi){
__b31, __b30, __b29, __b28, __b27, __b26, __b25, __b24,
- __b23, __b22, __b21, __b20, __b19, __b18, __b17, __b16,
- __b15, __b14, __b13, __b12, __b11, __b10, __b09, __b08,
- __b07, __b06, __b05, __b04, __b03, __b02, __b01, __b00 };
+ __b23, __b22, __b21, __b20, __b19, __b18, __b17, __b16,
+ __b15, __b14, __b13, __b12, __b11, __b10, __b09, __b08,
+ __b07, __b06, __b05, __b04, __b03, __b02, __b01, __b00 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi64x(long long __a, long long __b, long long __c, long long __d)
{
return (__m256i)(__v4di){ __a, __b, __c, __d };
}
/* Create vectors with repeated elements */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set1_pd(double __w)
{
return (__m256d){ __w, __w, __w, __w };
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_set1_ps(float __w)
{
return (__m256){ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi32(int __i)
{
return (__m256i)(__v8si){ __i, __i, __i, __i, __i, __i, __i, __i };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi16(short __w)
{
return (__m256i)(__v16hi){ __w, __w, __w, __w, __w, __w, __w, __w, __w, __w,
__w, __w, __w, __w, __w, __w };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi8(char __b)
{
return (__m256i)(__v32qi){ __b, __b, __b, __b, __b, __b, __b, __b, __b, __b,
@@ -1069,106 +1042,170 @@ _mm256_set1_epi8(char __b)
__b, __b, __b, __b, __b, __b, __b };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi64x(long long __q)
{
return (__m256i)(__v4di){ __q, __q, __q, __q };
}
/* Create __zeroed vectors */
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setzero_pd(void)
{
return (__m256d){ 0, 0, 0, 0 };
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setzero_ps(void)
{
return (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setzero_si256(void)
{
return (__m256i){ 0LL, 0LL, 0LL, 0LL };
}
/* Cast between vector types */
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_castpd_ps(__m256d __a)
{
return (__m256)__a;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castpd_si256(__m256d __a)
{
return (__m256i)__a;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_castps_pd(__m256 __a)
{
return (__m256d)__a;
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castps_si256(__m256 __a)
{
return (__m256i)__a;
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_castsi256_ps(__m256i __a)
{
return (__m256)__a;
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_castsi256_pd(__m256i __a)
{
return (__m256d)__a;
}
-static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline __m128d __DEFAULT_FN_ATTRS
_mm256_castpd256_pd128(__m256d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1);
}
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm256_castps256_ps128(__m256 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3);
}
-static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline __m128i __DEFAULT_FN_ATTRS
_mm256_castsi256_si128(__m256i __a)
{
return __builtin_shufflevector(__a, __a, 0, 1);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_castpd128_pd256(__m128d __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, -1, -1);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_castps128_ps256(__m128 __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, -1, -1, -1, -1);
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castsi128_si256(__m128i __a)
{
return __builtin_shufflevector(__a, __a, 0, 1, -1, -1);
}
+/*
+ Vector insert.
+ We use macros rather than inlines because we only want to accept
+ invocations where the immediate M is a constant expression.
+*/
+#define _mm256_insertf128_ps(V1, V2, M) __extension__ ({ \
+ (__m256)__builtin_shufflevector( \
+ (__v8sf)(V1), \
+ (__v8sf)_mm256_castps128_ps256((__m128)(V2)), \
+ (((M) & 1) ? 0 : 8), \
+ (((M) & 1) ? 1 : 9), \
+ (((M) & 1) ? 2 : 10), \
+ (((M) & 1) ? 3 : 11), \
+ (((M) & 1) ? 8 : 4), \
+ (((M) & 1) ? 9 : 5), \
+ (((M) & 1) ? 10 : 6), \
+ (((M) & 1) ? 11 : 7) );})
+
+#define _mm256_insertf128_pd(V1, V2, M) __extension__ ({ \
+ (__m256d)__builtin_shufflevector( \
+ (__v4df)(V1), \
+ (__v4df)_mm256_castpd128_pd256((__m128d)(V2)), \
+ (((M) & 1) ? 0 : 4), \
+ (((M) & 1) ? 1 : 5), \
+ (((M) & 1) ? 4 : 2), \
+ (((M) & 1) ? 5 : 3) );})
+
+#define _mm256_insertf128_si256(V1, V2, M) __extension__ ({ \
+ (__m256i)__builtin_shufflevector( \
+ (__v4di)(V1), \
+ (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
+ (((M) & 1) ? 0 : 4), \
+ (((M) & 1) ? 1 : 5), \
+ (((M) & 1) ? 4 : 2), \
+ (((M) & 1) ? 5 : 3) );})
+
+/*
+ Vector extract.
+ We use macros rather than inlines because we only want to accept
+ invocations where the immediate M is a constant expression.
+*/
+#define _mm256_extractf128_ps(V, M) __extension__ ({ \
+ (__m128)__builtin_shufflevector( \
+ (__v8sf)(V), \
+ (__v8sf)(_mm256_setzero_ps()), \
+ (((M) & 1) ? 4 : 0), \
+ (((M) & 1) ? 5 : 1), \
+ (((M) & 1) ? 6 : 2), \
+ (((M) & 1) ? 7 : 3) );})
+
+#define _mm256_extractf128_pd(V, M) __extension__ ({ \
+ (__m128d)__builtin_shufflevector( \
+ (__v4df)(V), \
+ (__v4df)(_mm256_setzero_pd()), \
+ (((M) & 1) ? 2 : 0), \
+ (((M) & 1) ? 3 : 1) );})
+
+#define _mm256_extractf128_si256(V, M) __extension__ ({ \
+ (__m128i)__builtin_shufflevector( \
+ (__v4di)(V), \
+ (__v4di)(_mm256_setzero_si256()), \
+ (((M) & 1) ? 2 : 0), \
+ (((M) & 1) ? 3 : 1) );})
+
/* SIMD load ops (unaligned) */
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_loadu2_m128(float const *__addr_hi, float const *__addr_lo)
{
struct __loadu_ps {
@@ -1179,7 +1216,7 @@ _mm256_loadu2_m128(float const *__addr_hi, float const *__addr_lo)
return _mm256_insertf128_ps(__v256, ((struct __loadu_ps*)__addr_hi)->__v, 1);
}
-static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_loadu2_m128d(double const *__addr_hi, double const *__addr_lo)
{
struct __loadu_pd {
@@ -1190,12 +1227,12 @@ _mm256_loadu2_m128d(double const *__addr_hi, double const *__addr_lo)
return _mm256_insertf128_pd(__v256, ((struct __loadu_pd*)__addr_hi)->__v, 1);
}
-static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_loadu2_m128i(__m128i const *__addr_hi, __m128i const *__addr_lo)
{
struct __loadu_si128 {
__m128i __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
__m256i __v256 = _mm256_castsi128_si256(
((struct __loadu_si128*)__addr_lo)->__v);
return _mm256_insertf128_si256(__v256,
@@ -1203,7 +1240,7 @@ _mm256_loadu2_m128i(__m128i const *__addr_hi, __m128i const *__addr_lo)
}
/* SIMD store ops (unaligned) */
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128(float *__addr_hi, float *__addr_lo, __m256 __a)
{
__m128 __v128;
@@ -1214,7 +1251,7 @@ _mm256_storeu2_m128(float *__addr_hi, float *__addr_lo, __m256 __a)
__builtin_ia32_storeups(__addr_hi, __v128);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128d(double *__addr_hi, double *__addr_lo, __m256d __a)
{
__m128d __v128;
@@ -1225,7 +1262,7 @@ _mm256_storeu2_m128d(double *__addr_hi, double *__addr_lo, __m256d __a)
__builtin_ia32_storeupd(__addr_hi, __v128);
}
-static __inline void __attribute__((__always_inline__, __nodebug__))
+static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128i(__m128i *__addr_hi, __m128i *__addr_lo, __m256i __a)
{
__m128i __v128;
@@ -1236,4 +1273,36 @@ _mm256_storeu2_m128i(__m128i *__addr_hi, __m128i *__addr_lo, __m256i __a)
__builtin_ia32_storedqu((char *)__addr_hi, (__v16qi)__v128);
}
+static __inline __m256 __DEFAULT_FN_ATTRS
+_mm256_set_m128 (__m128 __hi, __m128 __lo) {
+ return (__m256) __builtin_shufflevector(__lo, __hi, 0, 1, 2, 3, 4, 5, 6, 7);
+}
+
+static __inline __m256d __DEFAULT_FN_ATTRS
+_mm256_set_m128d (__m128d __hi, __m128d __lo) {
+ return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+}
+
+static __inline __m256i __DEFAULT_FN_ATTRS
+_mm256_set_m128i (__m128i __hi, __m128i __lo) {
+ return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+}
+
+static __inline __m256 __DEFAULT_FN_ATTRS
+_mm256_setr_m128 (__m128 __lo, __m128 __hi) {
+ return _mm256_set_m128(__hi, __lo);
+}
+
+static __inline __m256d __DEFAULT_FN_ATTRS
+_mm256_setr_m128d (__m128d __lo, __m128d __hi) {
+ return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+}
+
+static __inline __m256i __DEFAULT_FN_ATTRS
+_mm256_setr_m128i (__m128i __lo, __m128i __hi) {
+ return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __AVXINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h b/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
index a05cfad..c63397c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
@@ -32,19 +32,22 @@
#ifndef __BMI2INTRIN_H
#define __BMI2INTRIN_H
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_bzhi_u32(unsigned int __X, unsigned int __Y)
{
return __builtin_ia32_bzhi_si(__X, __Y);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_pdep_u32(unsigned int __X, unsigned int __Y)
{
return __builtin_ia32_pdep_si(__X, __Y);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_pext_u32(unsigned int __X, unsigned int __Y)
{
return __builtin_ia32_pext_si(__X, __Y);
@@ -52,25 +55,25 @@ _pext_u32(unsigned int __X, unsigned int __Y)
#ifdef __x86_64__
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_bzhi_u64(unsigned long long __X, unsigned long long __Y)
{
return __builtin_ia32_bzhi_di(__X, __Y);
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_pdep_u64(unsigned long long __X, unsigned long long __Y)
{
return __builtin_ia32_pdep_di(__X, __Y);
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_pext_u64(unsigned long long __X, unsigned long long __Y)
{
return __builtin_ia32_pext_di(__X, __Y);
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_mulx_u64 (unsigned long long __X, unsigned long long __Y,
unsigned long long *__P)
{
@@ -81,7 +84,7 @@ _mulx_u64 (unsigned long long __X, unsigned long long __Y,
#else /* !__x86_64__ */
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mulx_u32 (unsigned int __X, unsigned int __Y, unsigned int *__P)
{
unsigned long long __res = (unsigned long long) __X * __Y;
@@ -91,4 +94,6 @@ _mulx_u32 (unsigned int __X, unsigned int __Y, unsigned int *__P)
#endif /* !__x86_64__ */
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __BMI2INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
index 0e5fd55..0e93d57 100644
--- a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
@@ -40,51 +40,54 @@
#define _blsr_u32(a) (__blsr_u32((a)))
#define _tzcnt_u32(a) (__tzcnt_u32((a)))
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
__tzcnt_u16(unsigned short __X)
{
return __X ? __builtin_ctzs(__X) : 16;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__andn_u32(unsigned int __X, unsigned int __Y)
{
return ~__X & __Y;
}
/* AMD-specified, double-leading-underscore version of BEXTR */
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__bextr_u32(unsigned int __X, unsigned int __Y)
{
return __builtin_ia32_bextr_u32(__X, __Y);
}
/* Intel-specified, single-leading-underscore version of BEXTR */
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_bextr_u32(unsigned int __X, unsigned int __Y, unsigned int __Z)
{
return __builtin_ia32_bextr_u32 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blsi_u32(unsigned int __X)
{
return __X & -__X;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blsmsk_u32(unsigned int __X)
{
return __X ^ (__X - 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blsr_u32(unsigned int __X)
{
return __X & (__X - 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__tzcnt_u32(unsigned int __X)
{
return __X ? __builtin_ctz(__X) : 32;
@@ -99,45 +102,45 @@ __tzcnt_u32(unsigned int __X)
#define _blsr_u64(a) (__blsr_u64((a)))
#define _tzcnt_u64(a) (__tzcnt_u64((a)))
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__andn_u64 (unsigned long long __X, unsigned long long __Y)
{
return ~__X & __Y;
}
/* AMD-specified, double-leading-underscore version of BEXTR */
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__bextr_u64(unsigned long long __X, unsigned long long __Y)
{
return __builtin_ia32_bextr_u64(__X, __Y);
}
/* Intel-specified, single-leading-underscore version of BEXTR */
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_bextr_u64(unsigned long long __X, unsigned int __Y, unsigned int __Z)
{
return __builtin_ia32_bextr_u64 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsi_u64(unsigned long long __X)
{
return __X & -__X;
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsmsk_u64(unsigned long long __X)
{
return __X ^ (__X - 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsr_u64(unsigned long long __X)
{
return __X & (__X - 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__tzcnt_u64(unsigned long long __X)
{
return __X ? __builtin_ctzll(__X) : 64;
@@ -145,4 +148,6 @@ __tzcnt_u64(unsigned long long __X)
#endif /* __x86_64__ */
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __BMIINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/cuda_builtin_vars.h b/contrib/llvm/tools/clang/lib/Headers/cuda_builtin_vars.h
new file mode 100644
index 0000000..901356b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/cuda_builtin_vars.h
@@ -0,0 +1,110 @@
+/*===---- cuda_builtin_vars.h - CUDA built-in variables ---------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __CUDA_BUILTIN_VARS_H
+#define __CUDA_BUILTIN_VARS_H
+
+// The file implements built-in CUDA variables using __declspec(property).
+// https://msdn.microsoft.com/en-us/library/yhfk0thd.aspx
+// All read accesses of built-in variable fields get converted into calls to a
+// getter function which in turn would call appropriate builtin to fetch the
+// value.
+//
+// Example:
+// int x = threadIdx.x;
+// IR output:
+// %0 = call i32 @llvm.ptx.read.tid.x() #3
+// PTX output:
+// mov.u32 %r2, %tid.x;
+
+#define __CUDA_DEVICE_BUILTIN(FIELD, INTRINSIC) \
+ __declspec(property(get = __fetch_builtin_##FIELD)) unsigned int FIELD; \
+ static inline __attribute__((always_inline)) \
+ __attribute__((device)) unsigned int __fetch_builtin_##FIELD(void) { \
+ return INTRINSIC; \
+ }
+
+#if __cplusplus >= 201103L
+#define __DELETE =delete
+#else
+#define __DELETE
+#endif
+
+// Make sure nobody can create instances of the special varible types. nvcc
+// also disallows taking address of special variables, so we disable address-of
+// operator as well.
+#define __CUDA_DISALLOW_BUILTINVAR_ACCESS(TypeName) \
+ __attribute__((device)) TypeName() __DELETE; \
+ __attribute__((device)) TypeName(const TypeName &) __DELETE; \
+ __attribute__((device)) void operator=(const TypeName &) const __DELETE; \
+ __attribute__((device)) TypeName *operator&() const __DELETE
+
+struct __cuda_builtin_threadIdx_t {
+ __CUDA_DEVICE_BUILTIN(x,__builtin_ptx_read_tid_x());
+ __CUDA_DEVICE_BUILTIN(y,__builtin_ptx_read_tid_y());
+ __CUDA_DEVICE_BUILTIN(z,__builtin_ptx_read_tid_z());
+private:
+ __CUDA_DISALLOW_BUILTINVAR_ACCESS(__cuda_builtin_threadIdx_t);
+};
+
+struct __cuda_builtin_blockIdx_t {
+ __CUDA_DEVICE_BUILTIN(x,__builtin_ptx_read_ctaid_x());
+ __CUDA_DEVICE_BUILTIN(y,__builtin_ptx_read_ctaid_y());
+ __CUDA_DEVICE_BUILTIN(z,__builtin_ptx_read_ctaid_z());
+private:
+ __CUDA_DISALLOW_BUILTINVAR_ACCESS(__cuda_builtin_blockIdx_t);
+};
+
+struct __cuda_builtin_blockDim_t {
+ __CUDA_DEVICE_BUILTIN(x,__builtin_ptx_read_ntid_x());
+ __CUDA_DEVICE_BUILTIN(y,__builtin_ptx_read_ntid_y());
+ __CUDA_DEVICE_BUILTIN(z,__builtin_ptx_read_ntid_z());
+private:
+ __CUDA_DISALLOW_BUILTINVAR_ACCESS(__cuda_builtin_blockDim_t);
+};
+
+struct __cuda_builtin_gridDim_t {
+ __CUDA_DEVICE_BUILTIN(x,__builtin_ptx_read_nctaid_x());
+ __CUDA_DEVICE_BUILTIN(y,__builtin_ptx_read_nctaid_y());
+ __CUDA_DEVICE_BUILTIN(z,__builtin_ptx_read_nctaid_z());
+private:
+ __CUDA_DISALLOW_BUILTINVAR_ACCESS(__cuda_builtin_gridDim_t);
+};
+
+#define __CUDA_BUILTIN_VAR \
+ extern const __attribute__((device)) __attribute__((weak))
+__CUDA_BUILTIN_VAR __cuda_builtin_threadIdx_t threadIdx;
+__CUDA_BUILTIN_VAR __cuda_builtin_blockIdx_t blockIdx;
+__CUDA_BUILTIN_VAR __cuda_builtin_blockDim_t blockDim;
+__CUDA_BUILTIN_VAR __cuda_builtin_gridDim_t gridDim;
+
+// warpSize should translate to read of %WARP_SZ but there's currently no
+// builtin to do so. According to PTX v4.2 docs 'to date, all target
+// architectures have a WARP_SZ value of 32'.
+__attribute__((device)) const int warpSize = 32;
+
+#undef __CUDA_DEVICE_BUILTIN
+#undef __CUDA_BUILTIN_VAR
+#undef __CUDA_DISALLOW_BUILTINVAR_ACCESS
+
+#endif /* __CUDA_BUILTIN_VARS_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
index 28d0043..656bc19 100644
--- a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
@@ -39,433 +39,436 @@ typedef long long __v2di __attribute__ ((__vector_size__ (16)));
typedef short __v8hi __attribute__((__vector_size__(16)));
typedef char __v16qi __attribute__((__vector_size__(16)));
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_add_sd(__m128d __a, __m128d __b)
{
__a[0] += __b[0];
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_add_pd(__m128d __a, __m128d __b)
{
return __a + __b;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sub_sd(__m128d __a, __m128d __b)
{
__a[0] -= __b[0];
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sub_pd(__m128d __a, __m128d __b)
{
return __a - __b;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mul_sd(__m128d __a, __m128d __b)
{
__a[0] *= __b[0];
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mul_pd(__m128d __a, __m128d __b)
{
return __a * __b;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_div_sd(__m128d __a, __m128d __b)
{
__a[0] /= __b[0];
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_div_pd(__m128d __a, __m128d __b)
{
return __a / __b;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sqrt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_sqrtsd(__b);
return (__m128d) { __c[0], __a[1] };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sqrt_pd(__m128d __a)
{
return __builtin_ia32_sqrtpd(__a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_min_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_minsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_min_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_minpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_max_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_maxsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_max_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_maxpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_and_pd(__m128d __a, __m128d __b)
{
return (__m128d)((__v4si)__a & (__v4si)__b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_andnot_pd(__m128d __a, __m128d __b)
{
return (__m128d)(~(__v4si)__a & (__v4si)__b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_or_pd(__m128d __a, __m128d __b)
{
return (__m128d)((__v4si)__a | (__v4si)__b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_xor_pd(__m128d __a, __m128d __b)
{
return (__m128d)((__v4si)__a ^ (__v4si)__b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpeq_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpeqpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmplt_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpltpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmple_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmplepd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpgt_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpltpd(__b, __a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpge_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmplepd(__b, __a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpord_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpordpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpunord_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpunordpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpneq_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpneqpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnlt_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnltpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnle_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnlepd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpngt_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnltpd(__b, __a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnge_pd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnlepd(__b, __a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpeq_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpeqsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmplt_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpltsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmple_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmplesd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpgt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpltsd(__b, __a);
return (__m128d) { __c[0], __a[1] };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpge_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmplesd(__b, __a);
return (__m128d) { __c[0], __a[1] };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpord_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpordsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpunord_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpunordsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpneq_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpneqsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnlt_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnltsd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnle_sd(__m128d __a, __m128d __b)
{
return (__m128d)__builtin_ia32_cmpnlesd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpngt_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpnltsd(__b, __a);
return (__m128d) { __c[0], __a[1] };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnge_sd(__m128d __a, __m128d __b)
{
__m128d __c = __builtin_ia32_cmpnlesd(__b, __a);
return (__m128d) { __c[0], __a[1] };
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comieq_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdeq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comilt_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdlt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comile_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdle(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comigt_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdgt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comige_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdge(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comineq_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_comisdneq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomieq_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdeq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomilt_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdlt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomile_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdle(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomigt_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdgt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomige_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdge(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomineq_sd(__m128d __a, __m128d __b)
{
return __builtin_ia32_ucomisdneq(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpd_ps(__m128d __a)
{
return __builtin_ia32_cvtpd2ps(__a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtps_pd(__m128 __a)
{
return __builtin_ia32_cvtps2pd(__a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtepi32_pd(__m128i __a)
{
return __builtin_ia32_cvtdq2pd((__v4si)__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtpd_epi32(__m128d __a)
{
return __builtin_ia32_cvtpd2dq(__a);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtsd_si32(__m128d __a)
{
return __builtin_ia32_cvtsd2si(__a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtsd_ss(__m128 __a, __m128d __b)
{
__a[0] = __b[0];
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtsi32_sd(__m128d __a, int __b)
{
__a[0] = __b;
return __a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtss_sd(__m128d __a, __m128 __b)
{
__a[0] = __b[0];
return __a;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvttpd_epi32(__m128d __a)
{
return (__m128i)__builtin_ia32_cvttpd2dq(__a);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvttsd_si32(__m128d __a)
{
return __a[0];
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtpd_pi32(__m128d __a)
{
return (__m64)__builtin_ia32_cvtpd2pi(__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvttpd_pi32(__m128d __a)
{
return (__m64)__builtin_ia32_cvttpd2pi(__a);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtpi32_pd(__m64 __a)
{
return __builtin_ia32_cvtpi2pd((__v2si)__a);
}
-static __inline__ double __attribute__((__always_inline__, __nodebug__))
+static __inline__ double __DEFAULT_FN_ATTRS
_mm_cvtsd_f64(__m128d __a)
{
return __a[0];
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_load_pd(double const *__dp)
{
return *(__m128d*)__dp;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_load1_pd(double const *__dp)
{
struct __mm_load1_pd_struct {
@@ -477,23 +480,23 @@ _mm_load1_pd(double const *__dp)
#define _mm_load_pd1(dp) _mm_load1_pd(dp)
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadr_pd(double const *__dp)
{
__m128d __u = *(__m128d*)__dp;
return __builtin_shufflevector(__u, __u, 1, 0);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadu_pd(double const *__dp)
{
struct __loadu_pd {
__m128d __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_pd*)__dp)->__v;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_load_sd(double const *__dp)
{
struct __mm_load_sd_struct {
@@ -503,7 +506,7 @@ _mm_load_sd(double const *__dp)
return (__m128d){ __u, 0 };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadh_pd(__m128d __a, double const *__dp)
{
struct __mm_loadh_pd_struct {
@@ -513,7 +516,7 @@ _mm_loadh_pd(__m128d __a, double const *__dp)
return (__m128d){ __a[0], __u };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadl_pd(__m128d __a, double const *__dp)
{
struct __mm_loadl_pd_struct {
@@ -523,43 +526,43 @@ _mm_loadl_pd(__m128d __a, double const *__dp)
return (__m128d){ __u, __a[1] };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_sd(double __w)
{
return (__m128d){ __w, 0 };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set1_pd(double __w)
{
return (__m128d){ __w, __w };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_pd(double __w, double __x)
{
return (__m128d){ __x, __w };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setr_pd(double __w, double __x)
{
return (__m128d){ __w, __x };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setzero_pd(void)
{
return (__m128d){ 0, 0 };
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_move_sd(__m128d __a, __m128d __b)
{
return (__m128d){ __b[0], __a[1] };
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_sd(double *__dp, __m128d __a)
{
struct __mm_store_sd_struct {
@@ -568,7 +571,7 @@ _mm_store_sd(double *__dp, __m128d __a)
((struct __mm_store_sd_struct*)__dp)->__u = __a[0];
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store1_pd(double *__dp, __m128d __a)
{
struct __mm_store1_pd_struct {
@@ -578,26 +581,26 @@ _mm_store1_pd(double *__dp, __m128d __a)
((struct __mm_store1_pd_struct*)__dp)->__u[1] = __a[0];
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_pd(double *__dp, __m128d __a)
{
*(__m128d *)__dp = __a;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeu_pd(double *__dp, __m128d __a)
{
__builtin_ia32_storeupd(__dp, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storer_pd(double *__dp, __m128d __a)
{
__a = __builtin_shufflevector(__a, __a, 1, 0);
*(__m128d *)__dp = __a;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeh_pd(double *__dp, __m128d __a)
{
struct __mm_storeh_pd_struct {
@@ -606,7 +609,7 @@ _mm_storeh_pd(double *__dp, __m128d __a)
((struct __mm_storeh_pd_struct*)__dp)->__u = __a[1];
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storel_pd(double *__dp, __m128d __a)
{
struct __mm_storeh_pd_struct {
@@ -615,344 +618,377 @@ _mm_storel_pd(double *__dp, __m128d __a)
((struct __mm_storeh_pd_struct*)__dp)->__u = __a[0];
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_add_epi8(__m128i __a, __m128i __b)
{
return (__m128i)((__v16qi)__a + (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_add_epi16(__m128i __a, __m128i __b)
{
return (__m128i)((__v8hi)__a + (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_add_epi32(__m128i __a, __m128i __b)
{
return (__m128i)((__v4si)__a + (__v4si)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_add_si64(__m64 __a, __m64 __b)
{
return __a + __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_add_epi64(__m128i __a, __m128i __b)
{
return __a + __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_adds_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_paddsb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_adds_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_paddsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_adds_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_paddusb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_adds_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_paddusw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pavgb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pavgw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_madd_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmaddwd128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmaxsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmaxub128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pminsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pminub128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mulhi_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmulhw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mulhi_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmulhuw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mullo_epi16(__m128i __a, __m128i __b)
{
return (__m128i)((__v8hi)__a * (__v8hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_mul_su32(__m64 __a, __m64 __b)
{
return __builtin_ia32_pmuludq((__v2si)__a, (__v2si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mul_epu32(__m128i __a, __m128i __b)
{
return __builtin_ia32_pmuludq128((__v4si)__a, (__v4si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sad_epu8(__m128i __a, __m128i __b)
{
return __builtin_ia32_psadbw128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sub_epi8(__m128i __a, __m128i __b)
{
return (__m128i)((__v16qi)__a - (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sub_epi16(__m128i __a, __m128i __b)
{
return (__m128i)((__v8hi)__a - (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sub_epi32(__m128i __a, __m128i __b)
{
return (__m128i)((__v4si)__a - (__v4si)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_si64(__m64 __a, __m64 __b)
{
return __a - __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sub_epi64(__m128i __a, __m128i __b)
{
return __a - __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_subs_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psubsb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_subs_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psubsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_subs_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psubusb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_subs_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psubusw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_and_si128(__m128i __a, __m128i __b)
{
return __a & __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_andnot_si128(__m128i __a, __m128i __b)
{
return ~__a & __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_or_si128(__m128i __a, __m128i __b)
{
return __a | __b;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_xor_si128(__m128i __a, __m128i __b)
{
return __a ^ __b;
}
-#define _mm_slli_si128(a, count) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128i __a = (a); \
- _Pragma("clang diagnostic pop"); \
- (__m128i)__builtin_ia32_pslldqi128(__a, (count)*8); })
-
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+#define _mm_slli_si128(a, imm) __extension__ ({ \
+ (__m128i)__builtin_shufflevector((__v16qi)_mm_setzero_si128(), \
+ (__v16qi)(__m128i)(a), \
+ ((imm)&0xF0) ? 0 : 16 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 17 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 18 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 19 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 20 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 21 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 22 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 23 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 24 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 25 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 26 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 27 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 28 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 29 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 30 - ((imm)&0xF), \
+ ((imm)&0xF0) ? 0 : 31 - ((imm)&0xF)); })
+
+#define _mm_bslli_si128(a, imm) \
+ _mm_slli_si128((a), (imm))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi16(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_psllwi128((__v8hi)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi16(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_psllw128((__v8hi)__a, (__v8hi)__count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi32(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_pslldi128((__v4si)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi32(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_pslld128((__v4si)__a, (__v4si)__count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi64(__m128i __a, int __count)
{
return __builtin_ia32_psllqi128(__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi64(__m128i __a, __m128i __count)
{
return __builtin_ia32_psllq128(__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srai_epi16(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_psrawi128((__v8hi)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sra_epi16(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_psraw128((__v8hi)__a, (__v8hi)__count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srai_epi32(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_psradi128((__v4si)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sra_epi32(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_psrad128((__v4si)__a, (__v4si)__count);
}
-
-#define _mm_srli_si128(a, count) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128i __a = (a); \
- _Pragma("clang diagnostic pop"); \
- (__m128i)__builtin_ia32_psrldqi128(__a, (count)*8); })
-
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+#define _mm_srli_si128(a, imm) __extension__ ({ \
+ (__m128i)__builtin_shufflevector((__v16qi)(__m128i)(a), \
+ (__v16qi)_mm_setzero_si128(), \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 0, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 1, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 2, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 3, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 4, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 5, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 6, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 7, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 8, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 9, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 10, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 11, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 12, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 13, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 14, \
+ ((imm)&0xF0) ? 16 : ((imm)&0xF) + 15); })
+
+#define _mm_bsrli_si128(a, imm) \
+ _mm_srli_si128((a), (imm))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi16(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_psrlwi128((__v8hi)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi16(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_psrlw128((__v8hi)__a, (__v8hi)__count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi32(__m128i __a, int __count)
{
return (__m128i)__builtin_ia32_psrldi128((__v4si)__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi32(__m128i __a, __m128i __count)
{
return (__m128i)__builtin_ia32_psrld128((__v4si)__a, (__v4si)__count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi64(__m128i __a, int __count)
{
return __builtin_ia32_psrlqi128(__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi64(__m128i __a, __m128i __count)
{
return __builtin_ia32_psrlq128(__a, __count);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpeq_epi8(__m128i __a, __m128i __b)
{
return (__m128i)((__v16qi)__a == (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpeq_epi16(__m128i __a, __m128i __b)
{
return (__m128i)((__v8hi)__a == (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpeq_epi32(__m128i __a, __m128i __b)
{
return (__m128i)((__v4si)__a == (__v4si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpgt_epi8(__m128i __a, __m128i __b)
{
/* This function always performs a signed comparison, but __v16qi is a char
@@ -961,90 +997,90 @@ _mm_cmpgt_epi8(__m128i __a, __m128i __b)
return (__m128i)((__v16qs)__a > (__v16qs)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpgt_epi16(__m128i __a, __m128i __b)
{
return (__m128i)((__v8hi)__a > (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpgt_epi32(__m128i __a, __m128i __b)
{
return (__m128i)((__v4si)__a > (__v4si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmplt_epi8(__m128i __a, __m128i __b)
{
return _mm_cmpgt_epi8(__b, __a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmplt_epi16(__m128i __a, __m128i __b)
{
return _mm_cmpgt_epi16(__b, __a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmplt_epi32(__m128i __a, __m128i __b)
{
return _mm_cmpgt_epi32(__b, __a);
}
#ifdef __x86_64__
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtsi64_sd(__m128d __a, long long __b)
{
__a[0] = __b;
return __a;
}
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvtsd_si64(__m128d __a)
{
return __builtin_ia32_cvtsd2si64(__a);
}
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvttsd_si64(__m128d __a)
{
return __a[0];
}
#endif
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtepi32_ps(__m128i __a)
{
return __builtin_ia32_cvtdq2ps((__v4si)__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtps_epi32(__m128 __a)
{
return (__m128i)__builtin_ia32_cvtps2dq(__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvttps_epi32(__m128 __a)
{
return (__m128i)__builtin_ia32_cvttps2dq(__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi32_si128(int __a)
{
return (__m128i)(__v4si){ __a, 0, 0, 0 };
}
#ifdef __x86_64__
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi64_si128(long long __a)
{
return (__m128i){ __a, 0 };
}
#endif
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtsi128_si32(__m128i __a)
{
__v4si __b = (__v4si)__a;
@@ -1052,29 +1088,29 @@ _mm_cvtsi128_si32(__m128i __a)
}
#ifdef __x86_64__
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvtsi128_si64(__m128i __a)
{
return __a[0];
}
#endif
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_load_si128(__m128i const *__p)
{
return *__p;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_loadu_si128(__m128i const *__p)
{
struct __loadu_si128 {
__m128i __v;
- } __attribute__((packed, may_alias));
+ } __attribute__((__packed__, __may_alias__));
return ((struct __loadu_si128*)__p)->__v;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_loadl_epi64(__m128i const *__p)
{
struct __mm_loadl_epi64_struct {
@@ -1083,115 +1119,115 @@ _mm_loadl_epi64(__m128i const *__p)
return (__m128i) { ((struct __mm_loadl_epi64_struct*)__p)->__u, 0};
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi64x(long long q1, long long q0)
{
return (__m128i){ q0, q1 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi64(__m64 q1, __m64 q0)
{
return (__m128i){ (long long)q0, (long long)q1 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi32(int i3, int i2, int i1, int i0)
{
return (__m128i)(__v4si){ i0, i1, i2, i3};
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi16(short w7, short w6, short w5, short w4, short w3, short w2, short w1, short w0)
{
return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set_epi8(char b15, char b14, char b13, char b12, char b11, char b10, char b9, char b8, char b7, char b6, char b5, char b4, char b3, char b2, char b1, char b0)
{
return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi64x(long long __q)
{
return (__m128i){ __q, __q };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi64(__m64 __q)
{
return (__m128i){ (long long)__q, (long long)__q };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi32(int __i)
{
return (__m128i)(__v4si){ __i, __i, __i, __i };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi16(short __w)
{
return (__m128i)(__v8hi){ __w, __w, __w, __w, __w, __w, __w, __w };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_set1_epi8(char __b)
{
return (__m128i)(__v16qi){ __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b, __b };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi64(__m64 q0, __m64 q1)
{
return (__m128i){ (long long)q0, (long long)q1 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi32(int i0, int i1, int i2, int i3)
{
return (__m128i)(__v4si){ i0, i1, i2, i3};
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi16(short w0, short w1, short w2, short w3, short w4, short w5, short w6, short w7)
{
return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi8(char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
{
return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setzero_si128(void)
{
return (__m128i){ 0LL, 0LL };
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_si128(__m128i *__p, __m128i __b)
{
*__p = __b;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeu_si128(__m128i *__p, __m128i __b)
{
__builtin_ia32_storedqu((char *)__p, (__v16qi)__b);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_maskmoveu_si128(__m128i __d, __m128i __n, char *__p)
{
__builtin_ia32_maskmovdqu((__v16qi)__d, (__v16qi)__n, __p);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storel_epi64(__m128i *__p, __m128i __a)
{
struct __mm_storel_epi64_struct {
@@ -1200,76 +1236,76 @@ _mm_storel_epi64(__m128i *__p, __m128i __a)
((struct __mm_storel_epi64_struct*)__p)->__u = __a[0];
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_pd(double *__p, __m128d __a)
{
__builtin_ia32_movntpd(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_si128(__m128i *__p, __m128i __a)
{
__builtin_ia32_movntdq(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_si32(int *__p, int __a)
{
__builtin_ia32_movnti(__p, __a);
}
#ifdef __x86_64__
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_si64(long long *__p, long long __a)
{
__builtin_ia32_movnti64(__p, __a);
}
#endif
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_clflush(void const *__p)
{
__builtin_ia32_clflush(__p);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_lfence(void)
{
__builtin_ia32_lfence();
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_mfence(void)
{
__builtin_ia32_mfence();
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_packs_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_packsswb128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_packs_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_packssdw128((__v4si)__a, (__v4si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_packus_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_packuswb128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_extract_epi16(__m128i __a, int __imm)
{
__v8hi __b = (__v8hi)__a;
return (unsigned short)__b[__imm & 7];
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_insert_epi16(__m128i __a, int __b, int __imm)
{
__v8hi __c = (__v8hi)__a;
@@ -1277,173 +1313,166 @@ _mm_insert_epi16(__m128i __a, int __b, int __imm)
return (__m128i)__c;
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_epi8(__m128i __a)
{
return __builtin_ia32_pmovmskb128((__v16qi)__a);
}
#define _mm_shuffle_epi32(a, imm) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128i __a = (a); \
- _Pragma("clang diagnostic pop"); \
- (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si) _mm_set1_epi32(0), \
+ (__m128i)__builtin_shufflevector((__v4si)(__m128i)(a), \
+ (__v4si)_mm_set1_epi32(0), \
(imm) & 0x3, ((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6); })
#define _mm_shufflelo_epi16(a, imm) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128i __a = (a); \
- _Pragma("clang diagnostic pop"); \
- (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi) _mm_set1_epi16(0), \
+ (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
+ (__v8hi)_mm_set1_epi16(0), \
(imm) & 0x3, ((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \
4, 5, 6, 7); })
#define _mm_shufflehi_epi16(a, imm) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128i __a = (a); \
- _Pragma("clang diagnostic pop"); \
- (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi) _mm_set1_epi16(0), \
+ (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
+ (__v8hi)_mm_set1_epi16(0), \
0, 1, 2, 3, \
4 + (((imm) & 0x03) >> 0), \
4 + (((imm) & 0x0c) >> 2), \
4 + (((imm) & 0x30) >> 4), \
4 + (((imm) & 0xc0) >> 6)); })
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpackhi_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v16qi)__a, (__v16qi)__b, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpackhi_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b, 4, 8+4, 5, 8+5, 6, 8+6, 7, 8+7);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpackhi_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 2, 4+2, 3, 4+3);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpackhi_epi64(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector(__a, __b, 1, 2+1);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpacklo_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v16qi)__a, (__v16qi)__b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpacklo_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b, 0, 8+0, 1, 8+1, 2, 8+2, 3, 8+3);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpacklo_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 0, 4+0, 1, 4+1);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_unpacklo_epi64(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_shufflevector(__a, __b, 0, 2+0);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_movepi64_pi64(__m128i __a)
{
return (__m64)__a[0];
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_movpi64_epi64(__m64 __a)
{
return (__m128i){ (long long)__a, 0 };
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_move_epi64(__m128i __a)
{
return __builtin_shufflevector(__a, (__m128i){ 0 }, 0, 2);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_unpackhi_pd(__m128d __a, __m128d __b)
{
return __builtin_shufflevector(__a, __b, 1, 2+1);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_unpacklo_pd(__m128d __a, __m128d __b)
{
return __builtin_shufflevector(__a, __b, 0, 2+0);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_pd(__m128d __a)
{
return __builtin_ia32_movmskpd(__a);
}
#define _mm_shuffle_pd(a, b, i) __extension__ ({ \
- _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\""); \
- __m128d __a = (a); \
- __m128d __b = (b); \
- _Pragma("clang diagnostic pop"); \
- __builtin_shufflevector(__a, __b, (i) & 1, (((i) & 2) >> 1) + 2); })
+ __builtin_shufflevector((__m128d)(a), (__m128d)(b), \
+ (i) & 1, (((i) & 2) >> 1) + 2); })
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_castpd_ps(__m128d __a)
{
return (__m128)__a;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_castpd_si128(__m128d __a)
{
return (__m128i)__a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_castps_pd(__m128 __a)
{
return (__m128d)__a;
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_castps_si128(__m128 __a)
{
return (__m128i)__a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_castsi128_ps(__m128i __a)
{
return (__m128)__a;
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_castsi128_pd(__m128i __a)
{
return (__m128d)__a;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_pause(void)
{
__asm__ volatile ("pause");
}
+#undef __DEFAULT_FN_ATTRS
+
#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))
#endif /* __SSE2__ */
diff --git a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
index f3614c0..3730ae0 100644
--- a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
@@ -35,6 +35,9 @@
typedef float __v8sf __attribute__ ((__vector_size__ (32)));
typedef float __m256 __attribute__ ((__vector_size__ (32)));
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
#define _mm_cvtps_ph(a, imm) __extension__ ({ \
__m128 __a = (a); \
(__m128i)__builtin_ia32_vcvtps2ph((__v4sf)__a, (imm)); })
@@ -43,16 +46,18 @@ typedef float __m256 __attribute__ ((__vector_size__ (32)));
__m256 __a = (a); \
(__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)__a, (imm)); })
-static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline __m128 __DEFAULT_FN_ATTRS
_mm_cvtph_ps(__m128i __a)
{
return (__m128)__builtin_ia32_vcvtph2ps((__v8hi)__a);
}
-static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_cvtph_ps(__m128i __a)
{
return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __F16CINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
index c30920d..d6405cf 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
@@ -34,198 +34,203 @@
#include <pmmintrin.h>
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_macc_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_macc_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_macc_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_macc_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmacc_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmacc_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmaddpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmacc_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmaddss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmacc_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmaddsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmsubss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmsubsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_maddsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_maddsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubaddpd(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_macc_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_macc_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_msub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_msub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_nmacc_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfnmaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_nmacc_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfnmaddpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_nmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfnmsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_nmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfnmsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_maddsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_maddsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_msubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmsubaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_msubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmsubaddpd256(__A, __B, __C);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __FMA4__ */
#endif /* __FMA4INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
index 6bfd5a8..ad693fe 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
@@ -32,198 +32,203 @@
# error "FMA instruction set is not enabled"
#else
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmaddpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmaddss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmaddsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfnmsubss(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfnmsubsd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmaddsubps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmaddsubpd(__A, __B, __C);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
return (__m128)__builtin_ia32_vfmsubaddps(__A, __B, __C);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
return (__m128d)__builtin_ia32_vfmsubaddpd(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfnmaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfnmaddpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfnmsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfnmsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmaddsubps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmaddsubpd256(__A, __B, __C);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
return (__m256)__builtin_ia32_vfmsubaddps256(__A, __B, __C);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
return (__m256d)__builtin_ia32_vfmsubaddpd256(__A, __B, __C);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __FMA__ */
#endif /* __FMAINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
new file mode 100644
index 0000000..2b3549c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
@@ -0,0 +1,55 @@
+/*===---- fxsrintrin.h - FXSR intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <fxsrintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __FXSRINTRIN_H
+#define __FXSRINTRIN_H
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_fxsave(void *__p) {
+ return __builtin_ia32_fxsave(__p);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_fxsave64(void *__p) {
+ return __builtin_ia32_fxsave64(__p);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_fxrstor(void *__p) {
+ return __builtin_ia32_fxrstor(__p);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_fxrstor64(void *__p) {
+ return __builtin_ia32_fxrstor64(__p);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/htmintrin.h b/contrib/llvm/tools/clang/lib/Headers/htmintrin.h
new file mode 100644
index 0000000..0088c7c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/htmintrin.h
@@ -0,0 +1,226 @@
+/*===---- htmintrin.h - Standard header for PowerPC HTM ---------------===*\
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __HTMINTRIN_H
+#define __HTMINTRIN_H
+
+#ifndef __HTM__
+#error "HTM instruction set not enabled"
+#endif
+
+#ifdef __powerpc__
+
+#include <stdint.h>
+
+typedef uint64_t texasr_t;
+typedef uint32_t texasru_t;
+typedef uint32_t texasrl_t;
+typedef uintptr_t tfiar_t;
+typedef uintptr_t tfhar_t;
+
+#define _HTM_STATE(CR0) ((CR0 >> 1) & 0x3)
+#define _HTM_NONTRANSACTIONAL 0x0
+#define _HTM_SUSPENDED 0x1
+#define _HTM_TRANSACTIONAL 0x2
+
+#define _TEXASR_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+ (((TEXASR) >> (63-(BITNUM))) & ((1<<(SIZE))-1))
+#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+ (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
+
+#define _TEXASR_FAILURE_CODE(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 7, 8)
+#define _TEXASRU_FAILURE_CODE(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 8)
+
+#define _TEXASR_FAILURE_PERSISTENT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 7, 1)
+#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
+
+#define _TEXASR_DISALLOWED(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 8, 1)
+#define _TEXASRU_DISALLOWED(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 8, 1)
+
+#define _TEXASR_NESTING_OVERFLOW(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 9, 1)
+#define _TEXASRU_NESTING_OVERFLOW(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 9, 1)
+
+#define _TEXASR_FOOTPRINT_OVERFLOW(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 10, 1)
+#define _TEXASRU_FOOTPRINT_OVERFLOW(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 10, 1)
+
+#define _TEXASR_SELF_INDUCED_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 11, 1)
+#define _TEXASRU_SELF_INDUCED_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 11, 1)
+
+#define _TEXASR_NON_TRANSACTIONAL_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 12, 1)
+#define _TEXASRU_NON_TRANSACTIONAL_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 12, 1)
+
+#define _TEXASR_TRANSACTION_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 13, 1)
+#define _TEXASRU_TRANSACTION_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 13, 1)
+
+#define _TEXASR_TRANSLATION_INVALIDATION_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 14, 1)
+#define _TEXASRU_TRANSLATION_INVALIDATION_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 14, 1)
+
+#define _TEXASR_IMPLEMENTAION_SPECIFIC(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 15, 1)
+#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1)
+
+#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 16, 1)
+#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1)
+
+#define _TEXASR_ABORT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 31, 1)
+#define _TEXASRU_ABORT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 31, 1)
+
+
+#define _TEXASR_SUSPENDED(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 32, 1)
+
+#define _TEXASR_PRIVILEGE(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 35, 2)
+
+#define _TEXASR_FAILURE_SUMMARY(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 36, 1)
+
+#define _TEXASR_TFIAR_EXACT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 37, 1)
+
+#define _TEXASR_ROT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 38, 1)
+
+#define _TEXASR_TRANSACTION_LEVEL(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 63, 12)
+
+#endif /* __powerpc */
+
+#ifdef __s390__
+
+/* Condition codes generated by tbegin */
+#define _HTM_TBEGIN_STARTED 0
+#define _HTM_TBEGIN_INDETERMINATE 1
+#define _HTM_TBEGIN_TRANSIENT 2
+#define _HTM_TBEGIN_PERSISTENT 3
+
+/* The abort codes below this threshold are reserved for machine use. */
+#define _HTM_FIRST_USER_ABORT_CODE 256
+
+/* The transaction diagnostic block is it is defined in the Principles
+ of Operation chapter 5-91. */
+
+struct __htm_tdb {
+ unsigned char format; /* 0 */
+ unsigned char flags;
+ unsigned char reserved1[4];
+ unsigned short nesting_depth;
+ unsigned long long abort_code; /* 8 */
+ unsigned long long conflict_token; /* 16 */
+ unsigned long long atia; /* 24 */
+ unsigned char eaid; /* 32 */
+ unsigned char dxc;
+ unsigned char reserved2[2];
+ unsigned int program_int_id;
+ unsigned long long exception_id; /* 40 */
+ unsigned long long bea; /* 48 */
+ unsigned char reserved3[72]; /* 56 */
+ unsigned long long gprs[16]; /* 128 */
+} __attribute__((__packed__, __aligned__ (8)));
+
+
+/* Helper intrinsics to retry tbegin in case of transient failure. */
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_null (int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin(0)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_tdb (void *tdb, int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin(tdb)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+#define __builtin_tbegin_retry(tdb, retry) \
+ (__builtin_constant_p(tdb == 0) && tdb == 0 ? \
+ __builtin_tbegin_retry_null(retry) : \
+ __builtin_tbegin_retry_tdb(tdb, retry))
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_nofloat_null (int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin_nofloat(0)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+__builtin_tbegin_retry_nofloat_tdb (void *tdb, int retry)
+{
+ int cc, i = 0;
+
+ while ((cc = __builtin_tbegin_nofloat(tdb)) == _HTM_TBEGIN_TRANSIENT
+ && i++ < retry)
+ __builtin_tx_assist(i);
+
+ return cc;
+}
+
+#define __builtin_tbegin_retry_nofloat(tdb, retry) \
+ (__builtin_constant_p(tdb == 0) && tdb == 0 ? \
+ __builtin_tbegin_retry_nofloat_null(retry) : \
+ __builtin_tbegin_retry_nofloat_tdb(tdb, retry))
+
+#endif /* __s390__ */
+
+#endif /* __HTMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
new file mode 100644
index 0000000..30f524d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
@@ -0,0 +1,363 @@
+/*===---- htmxlintrin.h - XL compiler HTM execution intrinsics-------------===*\
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __HTMXLINTRIN_H
+#define __HTMXLINTRIN_H
+
+#ifndef __HTM__
+#error "HTM instruction set not enabled"
+#endif
+
+#include <htmintrin.h>
+
+#ifdef __powerpc__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _TEXASR_PTR(TM_BUF) \
+ ((texasr_t *)((TM_BUF)+0))
+#define _TEXASRU_PTR(TM_BUF) \
+ ((texasru_t *)((TM_BUF)+0))
+#define _TEXASRL_PTR(TM_BUF) \
+ ((texasrl_t *)((TM_BUF)+4))
+#define _TFIAR_PTR(TM_BUF) \
+ ((tfiar_t *)((TM_BUF)+8))
+
+typedef char TM_buff_type[16];
+
+/* This macro can be used to determine whether a transaction was successfully
+ started from the __TM_begin() and __TM_simple_begin() intrinsic functions
+ below. */
+#define _HTM_TBEGIN_STARTED 1
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_simple_begin (void)
+{
+ if (__builtin_expect (__builtin_tbegin (0), 1))
+ return _HTM_TBEGIN_STARTED;
+ return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_begin (void* const TM_buff)
+{
+ *_TEXASRL_PTR (TM_buff) = 0;
+ if (__builtin_expect (__builtin_tbegin (0), 1))
+ return _HTM_TBEGIN_STARTED;
+#ifdef __powerpc64__
+ *_TEXASR_PTR (TM_buff) = __builtin_get_texasr ();
+#else
+ *_TEXASRU_PTR (TM_buff) = __builtin_get_texasru ();
+ *_TEXASRL_PTR (TM_buff) = __builtin_get_texasr ();
+#endif
+ *_TFIAR_PTR (TM_buff) = __builtin_get_tfiar ();
+ return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_end (void)
+{
+ if (__builtin_expect (__builtin_tend (0), 1))
+ return 1;
+ return 0;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_abort (void)
+{
+ __builtin_tabort (0);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_named_abort (unsigned char const code)
+{
+ __builtin_tabort (code);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_resume (void)
+{
+ __builtin_tresume ();
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_suspend (void)
+{
+ __builtin_tsuspend ();
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_user_abort (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_named_user_abort (void* const TM_buff, unsigned char *code)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+
+ *code = _TEXASRU_FAILURE_CODE (texasru);
+ return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_illegal (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_DISALLOWED (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_footprint_exceeded (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_FOOTPRINT_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_nesting_depth (void* const TM_buff)
+{
+ texasrl_t texasrl;
+
+ if (_HTM_STATE (__builtin_ttest ()) == _HTM_NONTRANSACTIONAL)
+ {
+ texasrl = *_TEXASRL_PTR (TM_buff);
+ if (!_TEXASR_FAILURE_SUMMARY (texasrl))
+ texasrl = 0;
+ }
+ else
+ texasrl = (texasrl_t) __builtin_get_texasr ();
+
+ return _TEXASR_TRANSACTION_LEVEL (texasrl);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_nested_too_deep(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_NESTING_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_conflict(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ /* Return TEXASR bits 11 (Self-Induced Conflict) through
+ 14 (Translation Invalidation Conflict). */
+ return (_TEXASRU_EXTRACT_BITS (texasru, 14, 4)) ? 1 : 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_failure_persistent(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_FAILURE_PERSISTENT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_address(void* const TM_buff)
+{
+ return *_TFIAR_PTR (TM_buff);
+}
+
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_code(void* const TM_buff)
+{
+ return *_TEXASR_PTR (TM_buff);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __powerpc__ */
+
+#ifdef __s390__
+
+#include <stdint.h>
+
+/* These intrinsics are being made available for compatibility with
+ the IBM XL compiler. For documentation please see the "z/OS XL
+ C/C++ Programming Guide" publically available on the web. */
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_simple_begin ()
+{
+ return __builtin_tbegin_nofloat (0);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_begin (void* const tdb)
+{
+ return __builtin_tbegin_nofloat (tdb);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_end ()
+{
+ return __builtin_tend ();
+}
+
+static __inline void __attribute__((__always_inline__))
+__TM_abort ()
+{
+ return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+__TM_named_abort (unsigned char const code)
+{
+ return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+__TM_non_transactional_store (void* const addr, long long const value)
+{
+ __builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_nesting_depth (void* const tdb_ptr)
+{
+ int depth = __builtin_tx_nesting_depth ();
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (depth != 0)
+ return depth;
+
+ if (tdb->format != 1)
+ return 0;
+ return tdb->nesting_depth;
+}
+
+/* Transaction failure diagnostics */
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_user_abort (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
+ {
+ *code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
+ return 1;
+ }
+ return 0;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_illegal (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 4 /* unfiltered program interruption */
+ || tdb->abort_code == 11 /* restricted instruction */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_footprint_exceeded (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 7 /* fetch overflow */
+ || tdb->abort_code == 8 /* store overflow */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_nested_too_deep (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_conflict (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 9 /* fetch conflict */
+ || tdb->abort_code == 10 /* store conflict */));
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_is_failure_persistent (long const result)
+{
+ return result == _HTM_TBEGIN_PERSISTENT;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_failure_address (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+ return tdb->atia;
+}
+
+static __inline long __attribute__((__always_inline__, __nodebug__))
+__TM_failure_code (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->abort_code;
+}
+
+#endif /* __s390__ */
+
+#endif /* __HTMXLINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/immintrin.h b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
index 2400fea..21ad328 100644
--- a/contrib/llvm/tools/clang/lib/Headers/immintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
@@ -88,10 +88,22 @@
#include <avx512bwintrin.h>
#endif
+#ifdef __AVX512CD__
+#include <avx512cdintrin.h>
+#endif
+
+#ifdef __AVX512DQ__
+#include <avx512dqintrin.h>
+#endif
+
#if defined (__AVX512VL__) && defined (__AVX512BW__)
#include <avx512vlbwintrin.h>
#endif
+#if defined (__AVX512VL__) && defined (__AVX512DQ__)
+#include <avx512vldqintrin.h>
+#endif
+
#ifdef __AVX512ER__
#include <avx512erintrin.h>
#endif
@@ -174,21 +186,18 @@ _writegsbase_u64(unsigned long long __V)
#include <rtmintrin.h>
#endif
-/* FIXME: check __HLE__ as well when HLE is supported. */
-#if defined (__RTM__)
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
-_xtest(void)
-{
- return __builtin_ia32_xtest();
-}
+#ifdef __RTM__
+#include <xtestintrin.h>
#endif
#ifdef __SHA__
#include <shaintrin.h>
#endif
-/* Some intrinsics inside adxintrin.h are available only if __ADX__ defined,
- * whereas others are also available if __ADX__ undefined */
+#include <fxsrintrin.h>
+
+/* Some intrinsics inside adxintrin.h are available only on processors with ADX,
+ * whereas others are also available at all times. */
#include <adxintrin.h>
#endif /* __IMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/inttypes.h b/contrib/llvm/tools/clang/lib/Headers/inttypes.h
new file mode 100644
index 0000000..3d59d14
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/inttypes.h
@@ -0,0 +1,102 @@
+/*===---- inttypes.h - Standard header for integer printf macros ----------===*\
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __CLANG_INTTYPES_H
+#define __CLANG_INTTYPES_H
+
+#include_next <inttypes.h>
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+/* MSVC headers define int32_t as int, but PRIx32 as "lx" instead of "x".
+ * This triggers format warnings, so fix it up here. */
+#undef PRId32
+#undef PRIdLEAST32
+#undef PRIdFAST32
+#undef PRIi32
+#undef PRIiLEAST32
+#undef PRIiFAST32
+#undef PRIo32
+#undef PRIoLEAST32
+#undef PRIoFAST32
+#undef PRIu32
+#undef PRIuLEAST32
+#undef PRIuFAST32
+#undef PRIx32
+#undef PRIxLEAST32
+#undef PRIxFAST32
+#undef PRIX32
+#undef PRIXLEAST32
+#undef PRIXFAST32
+
+#undef SCNd32
+#undef SCNdLEAST32
+#undef SCNdFAST32
+#undef SCNi32
+#undef SCNiLEAST32
+#undef SCNiFAST32
+#undef SCNo32
+#undef SCNoLEAST32
+#undef SCNoFAST32
+#undef SCNu32
+#undef SCNuLEAST32
+#undef SCNuFAST32
+#undef SCNx32
+#undef SCNxLEAST32
+#undef SCNxFAST32
+
+#define PRId32 "d"
+#define PRIdLEAST32 "d"
+#define PRIdFAST32 "d"
+#define PRIi32 "i"
+#define PRIiLEAST32 "i"
+#define PRIiFAST32 "i"
+#define PRIo32 "o"
+#define PRIoLEAST32 "o"
+#define PRIoFAST32 "o"
+#define PRIu32 "u"
+#define PRIuLEAST32 "u"
+#define PRIuFAST32 "u"
+#define PRIx32 "x"
+#define PRIxLEAST32 "x"
+#define PRIxFAST32 "x"
+#define PRIX32 "X"
+#define PRIXLEAST32 "X"
+#define PRIXFAST32 "X"
+
+#define SCNd32 "d"
+#define SCNdLEAST32 "d"
+#define SCNdFAST32 "d"
+#define SCNi32 "i"
+#define SCNiLEAST32 "i"
+#define SCNiFAST32 "i"
+#define SCNo32 "o"
+#define SCNoLEAST32 "o"
+#define SCNoFAST32 "o"
+#define SCNu32 "u"
+#define SCNuLEAST32 "u"
+#define SCNuFAST32 "u"
+#define SCNx32 "x"
+#define SCNxLEAST32 "x"
+#define SCNxFAST32 "x"
+#endif
+
+#endif /* __CLANG_INTTYPES_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
index 35d6659..8ee2997 100644
--- a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
@@ -32,36 +32,41 @@
#ifndef __LZCNTINTRIN_H
#define __LZCNTINTRIN_H
-static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ unsigned short __DEFAULT_FN_ATTRS
__lzcnt16(unsigned short __X)
{
return __X ? __builtin_clzs(__X) : 16;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__lzcnt32(unsigned int __X)
{
return __X ? __builtin_clz(__X) : 32;
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_lzcnt_u32(unsigned int __X)
{
return __X ? __builtin_clz(__X) : 32;
}
#ifdef __x86_64__
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__lzcnt64(unsigned long long __X)
{
return __X ? __builtin_clzll(__X) : 64;
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_lzcnt_u64(unsigned long long __X)
{
return __X ? __builtin_clzll(__X) : 64;
}
#endif
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __LZCNTINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
index 5242d99..ac8e0f4 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
@@ -29,134 +29,139 @@
typedef float __v2sf __attribute__((__vector_size__(8)));
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ void __DEFAULT_FN_ATTRS
_m_femms() {
__builtin_ia32_femms();
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pavgusb(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pavgusb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pf2id(__m64 __m) {
return (__m64)__builtin_ia32_pf2id((__v2sf)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfacc(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfacc((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfadd(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfadd((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfcmpeq(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfcmpeq((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfcmpge(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfcmpge((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfcmpgt(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfcmpgt((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfmax(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfmax((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfmin(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfmin((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfmul(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfmul((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfrcp(__m64 __m) {
return (__m64)__builtin_ia32_pfrcp((__v2sf)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfrcpit1(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfrcpit1((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfrcpit2(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfrcpit2((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfrsqrt(__m64 __m) {
return (__m64)__builtin_ia32_pfrsqrt((__v2sf)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfrsqrtit1(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfrsqit1((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfsub(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfsub((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfsubr(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfsubr((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pi2fd(__m64 __m) {
return (__m64)__builtin_ia32_pi2fd((__v2si)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pmulhrw(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pmulhrw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pf2iw(__m64 __m) {
return (__m64)__builtin_ia32_pf2iw((__v2sf)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfnacc(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfnacc((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pfpnacc(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pfpnacc((__v2sf)__m1, (__v2sf)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pi2fw(__m64 __m) {
return (__m64)__builtin_ia32_pi2fw((__v2si)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pswapdsf(__m64 __m) {
return (__m64)__builtin_ia32_pswapdsf((__v2sf)__m);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pswapdsi(__m64 __m) {
return (__m64)__builtin_ia32_pswapdsi((__v2si)__m);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
index 986870a..0be5f32 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
@@ -34,367 +34,370 @@ typedef int __v2si __attribute__((__vector_size__(8)));
typedef short __v4hi __attribute__((__vector_size__(8)));
typedef char __v8qi __attribute__((__vector_size__(8)));
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_empty(void)
{
__builtin_ia32_emms();
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtsi32_si64(int __i)
{
return (__m64)__builtin_ia32_vec_init_v2si(__i, 0);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtsi64_si32(__m64 __m)
{
return __builtin_ia32_vec_ext_v2si((__v2si)__m, 0);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtsi64_m64(long long __i)
{
return (__m64)__i;
}
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvtm64_si64(__m64 __m)
{
return (long long)__m;
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_packs_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_packsswb((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_packs_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_packssdw((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_packs_pu16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_packuswb((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpackhi_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpckhbw((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpackhi_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpckhwd((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpackhi_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpckhdq((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpacklo_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpcklbw((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpacklo_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpcklwd((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_unpacklo_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_punpckldq((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_add_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_add_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_add_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddd((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_adds_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_adds_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_adds_pu8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_adds_pu16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddusw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubd((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_subs_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubsb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_subs_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubsw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_subs_pu8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubusb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_subs_pu16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubusw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_madd_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pmaddwd((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_mulhi_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pmulhw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_mullo_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pmullw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_pi16(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psllw((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_pi16(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psllwi((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_pi32(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_pslld((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_pi32(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_pslldi((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_si64(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psllq(__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_si64(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psllqi(__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sra_pi16(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psraw((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srai_pi16(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psrawi((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sra_pi32(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psrad((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srai_pi32(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psradi((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_pi16(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psrlw((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srli_pi16(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psrlwi((__v4hi)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_pi32(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psrld((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srli_pi32(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psrldi((__v2si)__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_si64(__m64 __m, __m64 __count)
{
return (__m64)__builtin_ia32_psrlq(__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srli_si64(__m64 __m, int __count)
{
return (__m64)__builtin_ia32_psrlqi(__m, __count);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_and_si64(__m64 __m1, __m64 __m2)
{
return __builtin_ia32_pand(__m1, __m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_andnot_si64(__m64 __m1, __m64 __m2)
{
return __builtin_ia32_pandn(__m1, __m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_or_si64(__m64 __m1, __m64 __m2)
{
return __builtin_ia32_por(__m1, __m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_xor_si64(__m64 __m1, __m64 __m2)
{
return __builtin_ia32_pxor(__m1, __m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpeq_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpeqb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpeq_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpeqw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpeq_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpeqd((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpgt_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpgtb((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpgt_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpgtw((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cmpgt_pi32(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pcmpgtd((__v2si)__m1, (__v2si)__m2);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_setzero_si64(void)
{
return (__m64){ 0LL };
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set_pi32(int __i1, int __i0)
{
return (__m64)__builtin_ia32_vec_init_v2si(__i0, __i1);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set_pi16(short __s3, short __s2, short __s1, short __s0)
{
return (__m64)__builtin_ia32_vec_init_v4hi(__s0, __s1, __s2, __s3);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
char __b1, char __b0)
{
@@ -402,43 +405,44 @@ _mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
__b4, __b5, __b6, __b7);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set1_pi32(int __i)
{
return _mm_set_pi32(__i, __i);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set1_pi16(short __w)
{
return _mm_set_pi16(__w, __w, __w, __w);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_set1_pi8(char __b)
{
return _mm_set_pi8(__b, __b, __b, __b, __b, __b, __b, __b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_setr_pi32(int __i0, int __i1)
{
return _mm_set_pi32(__i1, __i0);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_setr_pi16(short __w0, short __w1, short __w2, short __w3)
{
return _mm_set_pi16(__w3, __w2, __w1, __w0);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_setr_pi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5,
char __b6, char __b7)
{
return _mm_set_pi8(__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0);
}
+#undef __DEFAULT_FN_ATTRS
/* Aliases for compatibility. */
#define _m_empty _mm_empty
diff --git a/contrib/llvm/tools/clang/lib/Headers/module.modulemap b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
index 062464e..8fcb5bc 100644
--- a/contrib/llvm/tools/clang/lib/Headers/module.modulemap
+++ b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
@@ -49,7 +49,7 @@ module _Builtin_intrinsics [system] [extern_c] {
explicit module sse {
requires sse
export mmx
- export * // note: for hackish <emmintrin.h> dependency
+ export sse2 // note: for hackish <emmintrin.h> dependency
header "xmmintrin.h"
}
@@ -157,6 +157,8 @@ module _Builtin_intrinsics [system] [extern_c] {
explicit module aes_pclmul {
requires aes, pclmul
header "wmmintrin.h"
+ export aes
+ export pclmul
}
explicit module aes {
@@ -169,6 +171,19 @@ module _Builtin_intrinsics [system] [extern_c] {
header "__wmmintrin_pclmul.h"
}
}
+
+ explicit module systemz {
+ requires systemz
+ export *
+
+ header "s390intrin.h"
+
+ explicit module htm {
+ requires htm
+ header "htmintrin.h"
+ header "htmxlintrin.h"
+ }
+ }
}
module _Builtin_stddef_max_align_t [system] [extern_c] {
diff --git a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
index 6f1fc32..e1b8d9b 100644
--- a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
@@ -30,55 +30,58 @@
#include <emmintrin.h>
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_lddqu_si128(__m128i const *__p)
{
return (__m128i)__builtin_ia32_lddqu((char const *)__p);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_addsub_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_addsubps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_hadd_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_haddps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_hsub_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_hsubps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_movehdup_ps(__m128 __a)
{
return __builtin_shufflevector(__a, __a, 1, 1, 3, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_moveldup_ps(__m128 __a)
{
return __builtin_shufflevector(__a, __a, 0, 0, 2, 2);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_addsub_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_addsubpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_hadd_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_haddpd(__a, __b);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_hsub_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_hsubpd(__a, __b);
@@ -86,7 +89,7 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
#define _mm_loaddup_pd(dp) _mm_load1_pd(dp)
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_movedup_pd(__m128d __a)
{
return __builtin_shufflevector(__a, __a, 0, 0);
@@ -100,18 +103,20 @@ _mm_movedup_pd(__m128d __a)
#define _MM_GET_DENORMALS_ZERO_MODE() (_mm_getcsr() & _MM_DENORMALS_ZERO_MASK)
#define _MM_SET_DENORMALS_ZERO_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_DENORMALS_ZERO_MASK) | (x)))
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_monitor(void const *__p, unsigned __extensions, unsigned __hints)
{
__builtin_ia32_monitor((void *)__p, __extensions, __hints);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_mwait(unsigned __extensions, unsigned __hints)
{
__builtin_ia32_mwait(__extensions, __hints);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __SSE3__ */
#endif /* __PMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
index d439daa..1a4e900 100644
--- a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
@@ -28,18 +28,23 @@
#ifndef _POPCNTINTRIN_H
#define _POPCNTINTRIN_H
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_popcnt_u32(unsigned int __A)
{
return __builtin_popcount(__A);
}
#ifdef __x86_64__
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_popcnt_u64(unsigned long long __A)
{
return __builtin_popcountll(__A);
}
#endif /* __x86_64__ */
+#undef __DEFAULT_FN_ATTRS
+
#endif /* _POPCNTINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
index 0fef1fa..fdf7e18 100644
--- a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
@@ -29,24 +29,31 @@
#define __RDSEEDINTRIN_H
#ifdef __RDSEED__
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ int __DEFAULT_FN_ATTRS
_rdseed16_step(unsigned short *__p)
{
return __builtin_ia32_rdseed16_step(__p);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_rdseed32_step(unsigned int *__p)
{
return __builtin_ia32_rdseed32_step(__p);
}
#ifdef __x86_64__
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_rdseed64_step(unsigned long long *__p)
{
return __builtin_ia32_rdseed64_step(__p);
}
#endif
+
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __RDSEED__ */
#endif /* __RDSEEDINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h b/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
index 26149ca..1725681 100644
--- a/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
@@ -37,13 +37,16 @@
#define _XABORT_NESTED (1 << 5)
#define _XABORT_CODE(x) (((x) >> 24) & 0xFF)
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_xbegin(void)
{
return __builtin_ia32_xbegin();
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_xend(void)
{
__builtin_ia32_xend();
@@ -51,4 +54,6 @@ _xend(void)
#define _xabort(imm) __builtin_ia32_xabort((imm))
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __RTMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/s390intrin.h b/contrib/llvm/tools/clang/lib/Headers/s390intrin.h
new file mode 100644
index 0000000..b209895
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/s390intrin.h
@@ -0,0 +1,35 @@
+/*===---- s390intrin.h - SystemZ intrinsics --------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __S390INTRIN_H
+#define __S390INTRIN_H
+
+#ifndef __s390__
+#error "<s390intrin.h> is for s390 only"
+#endif
+
+#ifdef __HTM__
+#include <htmintrin.h>
+#endif
+
+#endif /* __S390INTRIN_H*/
diff --git a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
index 391a4bb..960cced 100644
--- a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
@@ -32,43 +32,48 @@
# error "SHA instructions not enabled"
#endif
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
#define _mm_sha1rnds4_epu32(V1, V2, M) __extension__ ({ \
__builtin_ia32_sha1rnds4((V1), (V2), (M)); })
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha1nexte_epu32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_sha1nexte((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha1msg1_epu32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_sha1msg1((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha1msg2_epu32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_sha1msg2((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha256rnds2_epu32(__m128i __X, __m128i __Y, __m128i __Z)
{
return (__m128i)__builtin_ia32_sha256rnds2((__v4si)__X, (__v4si)__Y, (__v4si)__Z);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha256msg1_epu32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_sha256msg1((__v4si)__X, (__v4si)__Y);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha256msg2_epu32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_sha256msg2((__v4si)__X, (__v4si)__Y);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __SHAINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
index 6e35734..04bd072 100644
--- a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
@@ -30,6 +30,9 @@
#include <tmmintrin.h>
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
/* SSE4 Rounding macros. */
#define _MM_FROUND_TO_NEAREST_INT 0x00
#define _MM_FROUND_TO_NEG_INF 0x01
@@ -92,21 +95,21 @@
(((M) & 0x04) ? 6 : 2), \
(((M) & 0x08) ? 7 : 3)); })
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
{
return (__m128d) __builtin_ia32_blendvpd ((__v2df)__V1, (__v2df)__V2,
(__v2df)__M);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
{
return (__m128) __builtin_ia32_blendvps ((__v4sf)__V1, (__v4sf)__V2,
(__v4sf)__M);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
{
return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__V1, (__v16qi)__V2,
@@ -127,13 +130,13 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
(((M) & 0x80) ? 15 : 7)); })
/* SSE4 Dword Multiply Instructions. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mullo_epi32 (__m128i __V1, __m128i __V2)
{
return (__m128i) ((__v4si)__V1 * (__v4si)__V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mul_epi32 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pmuldq128 ((__v4si)__V1, (__v4si)__V2);
@@ -151,56 +154,56 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
(__m128d) __builtin_ia32_dppd((__v2df)__X, (__v2df)__Y, (M)); })
/* SSE4 Streaming Load Hint Instruction. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_stream_load_si128 (__m128i *__V)
{
return (__m128i) __builtin_ia32_movntdqa ((__v2di *) __V);
}
/* SSE4 Packed Integer Min/Max Instructions. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epi8 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pminsb128 ((__v16qi) __V1, (__v16qi) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epi8 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi) __V1, (__v16qi) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epu16 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pminuw128 ((__v8hi) __V1, (__v8hi) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epu16 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi) __V1, (__v8hi) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epi32 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pminsd128 ((__v4si) __V1, (__v4si) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epi32 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si) __V1, (__v4si) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_min_epu32 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pminud128((__v4si) __V1, (__v4si) __V2);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_max_epu32 (__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pmaxud128((__v4si) __V1, (__v4si) __V2);
@@ -254,19 +257,19 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
#endif /* __x86_64 */
/* SSE4 128-bit Packed Integer Comparisons. */
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_testz_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestz128((__v2di)__M, (__v2di)__V);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_testc_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestc128((__v2di)__M, (__v2di)__V);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_testnzc_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestnzc128((__v2di)__M, (__v2di)__V);
@@ -277,88 +280,88 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V))
/* SSE4 64-bit Packed Integer Comparisons. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
{
return (__m128i)((__v2di)__V1 == (__v2di)__V2);
}
/* SSE4 Packed Integer Sign-Extension. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi16(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbw128((__v16qi) __V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbd128((__v16qi) __V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbq128((__v16qi) __V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxwd128((__v8hi) __V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxwq128((__v8hi)__V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi32_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxdq128((__v4si)__V);
}
/* SSE4 Packed Integer Zero-Extension. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi16(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbw128((__v16qi) __V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbd128((__v16qi)__V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu8_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbq128((__v16qi)__V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu16_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxwd128((__v8hi)__V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu16_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxwq128((__v8hi)__V);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepu32_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxdq128((__v4si)__V);
}
/* SSE4 Pack with Unsigned Saturation. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_packus_epi32(__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_packusdw128((__v4si)__V1, (__v4si)__V2);
@@ -370,7 +373,7 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
__m128i __Y = (Y); \
(__m128i) __builtin_ia32_mpsadbw128((__v16qi)__X, (__v16qi)__Y, (M)); })
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_minpos_epu16(__m128i __V)
{
return (__m128i) __builtin_ia32_phminposuw128((__v8hi)__V);
@@ -439,39 +442,41 @@ _mm_minpos_epu16(__m128i __V)
__builtin_ia32_pcmpestriz128((A), (LA), (B), (LB), (M))
/* SSE4.2 Compare Packed Data -- Greater Than. */
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
{
return (__m128i)((__v2di)__V1 > (__v2di)__V2);
}
/* SSE4.2 Accumulate CRC32. */
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mm_crc32_u8(unsigned int __C, unsigned char __D)
{
return __builtin_ia32_crc32qi(__C, __D);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mm_crc32_u16(unsigned int __C, unsigned short __D)
{
return __builtin_ia32_crc32hi(__C, __D);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mm_crc32_u32(unsigned int __C, unsigned int __D)
{
return __builtin_ia32_crc32si(__C, __D);
}
#ifdef __x86_64__
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_mm_crc32_u64(unsigned long long __C, unsigned long long __D)
{
return __builtin_ia32_crc32di(__C, __D);
}
#endif /* __x86_64__ */
+#undef __DEFAULT_FN_ATTRS
+
#ifdef __POPCNT__
#include <popcntintrin.h>
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdatomic.h b/contrib/llvm/tools/clang/lib/Headers/stdatomic.h
index e3c3476..e037987 100644
--- a/contrib/llvm/tools/clang/lib/Headers/stdatomic.h
+++ b/contrib/llvm/tools/clang/lib/Headers/stdatomic.h
@@ -71,7 +71,7 @@ typedef enum memory_order {
/* 7.17.4 Fences */
-// These should be provided by the libc implementation.
+/* These should be provided by the libc implementation. */
void atomic_thread_fence(memory_order);
void atomic_signal_fence(memory_order);
@@ -164,7 +164,7 @@ typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;
#define ATOMIC_FLAG_INIT { 0 }
-// These should be provided by the libc implementation.
+/* These should be provided by the libc implementation. */
#ifdef __cplusplus
bool atomic_flag_test_and_set(volatile atomic_flag *);
bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order);
diff --git a/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
index f95e34f..48c0b07 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
@@ -32,57 +32,60 @@
#ifndef __TBMINTRIN_H
#define __TBMINTRIN_H
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
#define __bextri_u32(a, b) (__builtin_ia32_bextri_u32((a), (b)))
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blcfill_u32(unsigned int a)
{
return a & (a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blci_u32(unsigned int a)
{
return a | ~(a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blcic_u32(unsigned int a)
{
return ~a & (a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blcmsk_u32(unsigned int a)
{
return a ^ (a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blcs_u32(unsigned int a)
{
return a | (a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blsfill_u32(unsigned int a)
{
return a | (a - 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blsic_u32(unsigned int a)
{
return ~a | (a - 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__t1mskc_u32(unsigned int a)
{
return ~a | (a + 1);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
__tzmsk_u32(unsigned int a)
{
return ~a & (a - 1);
@@ -91,68 +94,61 @@ __tzmsk_u32(unsigned int a)
#ifdef __x86_64__
#define __bextri_u64(a, b) (__builtin_ia32_bextri_u64((a), (int)(b)))
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blcfill_u64(unsigned long long a)
{
return a & (a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blci_u64(unsigned long long a)
{
return a | ~(a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blcic_u64(unsigned long long a)
{
return ~a & (a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blcmsk_u64(unsigned long long a)
{
return a ^ (a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blcs_u64(unsigned long long a)
{
return a | (a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsfill_u64(unsigned long long a)
{
return a | (a - 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsic_u64(unsigned long long a)
{
return ~a | (a - 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__t1mskc_u64(unsigned long long a)
{
return ~a | (a + 1);
}
-static __inline__ unsigned long long __attribute__((__always_inline__,
- __nodebug__))
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__tzmsk_u64(unsigned long long a)
{
return ~a & (a - 1);
}
#endif
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __TBMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
index 4238f5b..2ecc730 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
@@ -30,37 +30,40 @@
#include <pmmintrin.h>
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_abs_pi8(__m64 __a)
{
return (__m64)__builtin_ia32_pabsb((__v8qi)__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_abs_epi8(__m128i __a)
{
return (__m128i)__builtin_ia32_pabsb128((__v16qi)__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_abs_pi16(__m64 __a)
{
return (__m64)__builtin_ia32_pabsw((__v4hi)__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_abs_epi16(__m128i __a)
{
return (__m128i)__builtin_ia32_pabsw128((__v8hi)__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_abs_pi32(__m64 __a)
{
return (__m64)__builtin_ia32_pabsd((__v2si)__a);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_abs_epi32(__m128i __a)
{
return (__m128i)__builtin_ia32_pabsd128((__v4si)__a);
@@ -76,150 +79,152 @@ _mm_abs_epi32(__m128i __a)
__m64 __b = (b); \
(__m64)__builtin_ia32_palignr((__v8qi)__a, (__v8qi)__b, (n)); })
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hadd_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phaddw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hadd_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phaddd128((__v4si)__a, (__v4si)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hadd_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hadd_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddd((__v2si)__a, (__v2si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hadds_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phaddsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hadds_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phaddsw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsub_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phsubw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsub_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phsubd128((__v4si)__a, (__v4si)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hsub_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hsub_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubd((__v2si)__a, (__v2si)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsubs_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_phsubsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_hsubs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_phsubsw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maddubs_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmaddubsw128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_maddubs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaddubsw((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mulhrs_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmulhrsw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_mulhrs_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmulhrsw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shuffle_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pshufb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_shuffle_pi8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pshufb((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sign_epi8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psignb128((__v16qi)__a, (__v16qi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sign_epi16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psignw128((__v8hi)__a, (__v8hi)__b);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sign_epi32(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_psignd128((__v4si)__a, (__v4si)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sign_pi8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignb((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sign_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sign_pi32(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psignd((__v2si)__a, (__v2si)__b);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __SSSE3__ */
#endif /* __TMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/unwind.h b/contrib/llvm/tools/clang/lib/Headers/unwind.h
index 90aca16..303d792 100644
--- a/contrib/llvm/tools/clang/lib/Headers/unwind.h
+++ b/contrib/llvm/tools/clang/lib/Headers/unwind.h
@@ -235,9 +235,9 @@ void *_Unwind_FindEnclosingFunction(void *);
#ifdef __APPLE__
_Unwind_Ptr _Unwind_GetDataRelBase(struct _Unwind_Context *)
- __attribute__((unavailable));
+ __attribute__((__unavailable__));
_Unwind_Ptr _Unwind_GetTextRelBase(struct _Unwind_Context *)
- __attribute__((unavailable));
+ __attribute__((__unavailable__));
/* Darwin-specific functions */
void __register_frame(const void *);
@@ -251,15 +251,15 @@ struct dwarf_eh_bases {
void *_Unwind_Find_FDE(const void *, struct dwarf_eh_bases *);
void __register_frame_info_bases(const void *, void *, void *, void *)
- __attribute__((unavailable));
-void __register_frame_info(const void *, void *) __attribute__((unavailable));
+ __attribute__((__unavailable__));
+void __register_frame_info(const void *, void *) __attribute__((__unavailable__));
void __register_frame_info_table_bases(const void *, void*, void *, void *)
- __attribute__((unavailable));
+ __attribute__((__unavailable__));
void __register_frame_info_table(const void *, void *)
- __attribute__((unavailable));
-void __register_frame_table(const void *) __attribute__((unavailable));
-void __deregister_frame_info(const void *) __attribute__((unavailable));
-void __deregister_frame_info_bases(const void *)__attribute__((unavailable));
+ __attribute__((__unavailable__));
+void __register_frame_table(const void *) __attribute__((__unavailable__));
+void __deregister_frame_info(const void *) __attribute__((__unavailable__));
+void __deregister_frame_info_bases(const void *)__attribute__((__unavailable__));
#else
diff --git a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
index d1afe81..0d58c75 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
@@ -40,182 +40,185 @@ typedef float __m128 __attribute__((__vector_size__(16)));
#include <mm_malloc.h>
#endif
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_add_ss(__m128 __a, __m128 __b)
{
__a[0] += __b[0];
return __a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_add_ps(__m128 __a, __m128 __b)
{
return __a + __b;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sub_ss(__m128 __a, __m128 __b)
{
__a[0] -= __b[0];
return __a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sub_ps(__m128 __a, __m128 __b)
{
return __a - __b;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mul_ss(__m128 __a, __m128 __b)
{
__a[0] *= __b[0];
return __a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mul_ps(__m128 __a, __m128 __b)
{
return __a * __b;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_div_ss(__m128 __a, __m128 __b)
{
__a[0] /= __b[0];
return __a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_div_ps(__m128 __a, __m128 __b)
{
return __a / __b;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sqrt_ss(__m128 __a)
{
__m128 __c = __builtin_ia32_sqrtss(__a);
return (__m128) { __c[0], __a[1], __a[2], __a[3] };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sqrt_ps(__m128 __a)
{
return __builtin_ia32_sqrtps(__a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp_ss(__m128 __a)
{
__m128 __c = __builtin_ia32_rcpss(__a);
return (__m128) { __c[0], __a[1], __a[2], __a[3] };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp_ps(__m128 __a)
{
return __builtin_ia32_rcpps(__a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rsqrt_ss(__m128 __a)
{
__m128 __c = __builtin_ia32_rsqrtss(__a);
return (__m128) { __c[0], __a[1], __a[2], __a[3] };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rsqrt_ps(__m128 __a)
{
return __builtin_ia32_rsqrtps(__a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_min_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_minss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_min_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_minps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_max_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_maxss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_max_ps(__m128 __a, __m128 __b)
{
return __builtin_ia32_maxps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_and_ps(__m128 __a, __m128 __b)
{
return (__m128)((__v4si)__a & (__v4si)__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_andnot_ps(__m128 __a, __m128 __b)
{
return (__m128)(~(__v4si)__a & (__v4si)__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_or_ps(__m128 __a, __m128 __b)
{
return (__m128)((__v4si)__a | (__v4si)__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_xor_ps(__m128 __a, __m128 __b)
{
return (__m128)((__v4si)__a ^ (__v4si)__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpeq_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpeqss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpeq_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpeqps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmplt_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpltss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmplt_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpltps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmple_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpless(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmple_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpleps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpgt_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_shufflevector(__a,
@@ -223,13 +226,13 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpgt_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpltps(__b, __a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpge_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_shufflevector(__a,
@@ -237,49 +240,49 @@ _mm_cmpge_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpge_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpleps(__b, __a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpneq_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpneqss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpneq_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpneqps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnlt_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnltss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnlt_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnltps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnle_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnless(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnle_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnleps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpngt_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_shufflevector(__a,
@@ -287,13 +290,13 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpngt_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnltps(__b, __a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnge_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_shufflevector(__a,
@@ -301,115 +304,115 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b)
4, 1, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpnge_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpnleps(__b, __a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpord_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpordss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpord_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpordps(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpunord_ss(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpunordss(__a, __b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cmpunord_ps(__m128 __a, __m128 __b)
{
return (__m128)__builtin_ia32_cmpunordps(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comieq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comieq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comilt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comilt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comile_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comile(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comigt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comigt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comige_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comige(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_comineq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_comineq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomieq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomieq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomilt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomilt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomile_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomile(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomigt_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomigt(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomige_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomige(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomineq_ss(__m128 __a, __m128 __b)
{
return __builtin_ia32_ucomineq(__a, __b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtss_si32(__m128 __a)
{
return __builtin_ia32_cvtss2si(__a);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvt_ss2si(__m128 __a)
{
return _mm_cvtss_si32(__a);
@@ -417,7 +420,7 @@ _mm_cvt_ss2si(__m128 __a)
#ifdef __x86_64__
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvtss_si64(__m128 __a)
{
return __builtin_ia32_cvtss2si64(__a);
@@ -425,56 +428,56 @@ _mm_cvtss_si64(__m128 __a)
#endif
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtps_pi32(__m128 __a)
{
return (__m64)__builtin_ia32_cvtps2pi(__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvt_ps2pi(__m128 __a)
{
return _mm_cvtps_pi32(__a);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvttss_si32(__m128 __a)
{
return __a[0];
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtt_ss2si(__m128 __a)
{
return _mm_cvttss_si32(__a);
}
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ long long __DEFAULT_FN_ATTRS
_mm_cvttss_si64(__m128 __a)
{
return __a[0];
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvttps_pi32(__m128 __a)
{
return (__m64)__builtin_ia32_cvttps2pi(__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtt_ps2pi(__m128 __a)
{
return _mm_cvttps_pi32(__a);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtsi32_ss(__m128 __a, int __b)
{
__a[0] = __b;
return __a;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvt_si2ss(__m128 __a, int __b)
{
return _mm_cvtsi32_ss(__a, __b);
@@ -482,7 +485,7 @@ _mm_cvt_si2ss(__m128 __a, int __b)
#ifdef __x86_64__
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtsi64_ss(__m128 __a, long long __b)
{
__a[0] = __b;
@@ -491,25 +494,25 @@ _mm_cvtsi64_ss(__m128 __a, long long __b)
#endif
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi32_ps(__m128 __a, __m64 __b)
{
return __builtin_ia32_cvtpi2ps(__a, (__v2si)__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvt_pi2ps(__m128 __a, __m64 __b)
{
return _mm_cvtpi32_ps(__a, __b);
}
-static __inline__ float __attribute__((__always_inline__, __nodebug__))
+static __inline__ float __DEFAULT_FN_ATTRS
_mm_cvtss_f32(__m128 __a)
{
return __a[0];
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_loadh_pi(__m128 __a, const __m64 *__p)
{
typedef float __mm_loadh_pi_v2f32 __attribute__((__vector_size__(8)));
@@ -521,7 +524,7 @@ _mm_loadh_pi(__m128 __a, const __m64 *__p)
return __builtin_shufflevector(__a, __bb, 0, 1, 4, 5);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_loadl_pi(__m128 __a, const __m64 *__p)
{
typedef float __mm_loadl_pi_v2f32 __attribute__((__vector_size__(8)));
@@ -533,7 +536,7 @@ _mm_loadl_pi(__m128 __a, const __m64 *__p)
return __builtin_shufflevector(__a, __bb, 4, 5, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_load_ss(const float *__p)
{
struct __mm_load_ss_struct {
@@ -543,7 +546,7 @@ _mm_load_ss(const float *__p)
return (__m128){ __u, 0, 0, 0 };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_load1_ps(const float *__p)
{
struct __mm_load1_ps_struct {
@@ -555,13 +558,13 @@ _mm_load1_ps(const float *__p)
#define _mm_load_ps1(p) _mm_load1_ps(p)
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_load_ps(const float *__p)
{
return *(__m128*)__p;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_loadu_ps(const float *__p)
{
struct __loadu_ps {
@@ -570,63 +573,63 @@ _mm_loadu_ps(const float *__p)
return ((struct __loadu_ps*)__p)->__v;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_loadr_ps(const float *__p)
{
__m128 __a = _mm_load_ps(__p);
return __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ss(float __w)
{
return (__m128){ __w, 0, 0, 0 };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set1_ps(float __w)
{
return (__m128){ __w, __w, __w, __w };
}
/* Microsoft specific. */
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ps1(float __w)
{
return _mm_set1_ps(__w);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ps(float __z, float __y, float __x, float __w)
{
return (__m128){ __w, __x, __y, __z };
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setr_ps(float __z, float __y, float __x, float __w)
{
return (__m128){ __z, __y, __x, __w };
}
-static __inline__ __m128 __attribute__((__always_inline__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setzero_ps(void)
{
return (__m128){ 0, 0, 0, 0 };
}
-static __inline__ void __attribute__((__always_inline__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeh_pi(__m64 *__p, __m128 __a)
{
__builtin_ia32_storehps((__v2si *)__p, __a);
}
-static __inline__ void __attribute__((__always_inline__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storel_pi(__m64 *__p, __m128 __a)
{
__builtin_ia32_storelps((__v2si *)__p, __a);
}
-static __inline__ void __attribute__((__always_inline__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ss(float *__p, __m128 __a)
{
struct __mm_store_ss_struct {
@@ -635,32 +638,32 @@ _mm_store_ss(float *__p, __m128 __a)
((struct __mm_store_ss_struct*)__p)->__u = __a[0];
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeu_ps(float *__p, __m128 __a)
{
__builtin_ia32_storeups(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store1_ps(float *__p, __m128 __a)
{
__a = __builtin_shufflevector(__a, __a, 0, 0, 0, 0);
_mm_storeu_ps(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ps1(float *__p, __m128 __a)
{
return _mm_store1_ps(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ps(float *__p, __m128 __a)
{
*(__m128 *)__p = __a;
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_storer_ps(float *__p, __m128 __a)
{
__a = __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
@@ -679,32 +682,32 @@ _mm_storer_ps(float *__p, __m128 __a)
#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, (sel)))
#endif
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_pi(__m64 *__p, __m64 __a)
{
__builtin_ia32_movntq(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_stream_ps(float *__p, __m128 __a)
{
__builtin_ia32_movntps(__p, __a);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_sfence(void)
{
__builtin_ia32_sfence();
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_extract_pi16(__m64 __a, int __n)
{
__v4hi __b = (__v4hi)__a;
return (unsigned short)__b[__n & 3];
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_insert_pi16(__m64 __a, int __d, int __n)
{
__v4hi __b = (__v4hi)__a;
@@ -712,37 +715,37 @@ _mm_insert_pi16(__m64 __a, int __d, int __n)
return (__m64)__b;
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_max_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaxsw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_max_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmaxub((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_min_pi16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pminsw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_min_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pminub((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_pi8(__m64 __a)
{
return __builtin_ia32_pmovmskb((__v8qi)__a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_mulhi_pu16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pmulhuw((__v4hi)__a, (__v4hi)__b);
@@ -752,37 +755,37 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
__m64 __a = (a); \
(__m64)__builtin_ia32_pshufw((__v4hi)__a, (n)); })
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)
{
__builtin_ia32_maskmovq((__v8qi)__d, (__v8qi)__n, __p);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_avg_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pavgb((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_avg_pu16(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_pavgw((__v4hi)__a, (__v4hi)__b);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sad_pu8(__m64 __a, __m64 __b)
{
return (__m64)__builtin_ia32_psadbw((__v8qi)__a, (__v8qi)__b);
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mm_getcsr(void)
{
return __builtin_ia32_stmxcsr();
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __DEFAULT_FN_ATTRS
_mm_setcsr(unsigned int __i)
{
__builtin_ia32_ldmxcsr(__i);
@@ -796,37 +799,37 @@ _mm_setcsr(unsigned int __i)
(((mask) & 0x30) >> 4) + 4, \
(((mask) & 0xc0) >> 6) + 4); })
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_unpackhi_ps(__m128 __a, __m128 __b)
{
return __builtin_shufflevector(__a, __b, 2, 6, 3, 7);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_unpacklo_ps(__m128 __a, __m128 __b)
{
return __builtin_shufflevector(__a, __b, 0, 4, 1, 5);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_move_ss(__m128 __a, __m128 __b)
{
return __builtin_shufflevector(__a, __b, 4, 1, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_movehl_ps(__m128 __a, __m128 __b)
{
return __builtin_shufflevector(__a, __b, 6, 7, 2, 3);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_movelh_ps(__m128 __a, __m128 __b)
{
return __builtin_shufflevector(__a, __b, 0, 1, 4, 5);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi16_ps(__m64 __a)
{
__m64 __b, __c;
@@ -844,7 +847,7 @@ _mm_cvtpi16_ps(__m64 __a)
return __r;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpu16_ps(__m64 __a)
{
__m64 __b, __c;
@@ -861,7 +864,7 @@ _mm_cvtpu16_ps(__m64 __a)
return __r;
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi8_ps(__m64 __a)
{
__m64 __b;
@@ -873,7 +876,7 @@ _mm_cvtpi8_ps(__m64 __a)
return _mm_cvtpi16_ps(__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpu8_ps(__m64 __a)
{
__m64 __b;
@@ -884,7 +887,7 @@ _mm_cvtpu8_ps(__m64 __a)
return _mm_cvtpi16_ps(__b);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
{
__m128 __c;
@@ -896,7 +899,7 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
return _mm_cvtpi32_ps(__c, __a);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtps_pi16(__m128 __a)
{
__m64 __b, __c;
@@ -908,7 +911,7 @@ _mm_cvtps_pi16(__m128 __a)
return _mm_packs_pi32(__b, __c);
}
-static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtps_pi8(__m128 __a)
{
__m64 __b, __c;
@@ -919,7 +922,7 @@ _mm_cvtps_pi8(__m128 __a)
return _mm_packs_pi16(__b, __c);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_ps(__m128 __a)
{
return __builtin_ia32_movmskps(__a);
@@ -993,8 +996,10 @@ do { \
#define _m_ _mm_
#define _m_ _mm_
+#undef __DEFAULT_FN_ATTRS
+
/* Ugly hack for backwards-compatibility (compatible with gcc) */
-#ifdef __SSE2__
+#if defined(__SSE2__) && !__has_feature(modules)
#include <emmintrin.h>
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
index cc94ca0..2eb35c4 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
@@ -34,205 +34,208 @@
#include <fma4intrin.h>
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacssww((__v8hi)__A, (__v8hi)__B, (__v8hi)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_macc_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacsww((__v8hi)__A, (__v8hi)__B, (__v8hi)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccsd_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacsswd((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccd_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacswd((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccs_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacssdd((__v4si)__A, (__v4si)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_macc_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacsdd((__v4si)__A, (__v4si)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccslo_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacssdql((__v4si)__A, (__v4si)__B, (__v2di)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_macclo_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacsdql((__v4si)__A, (__v4si)__B, (__v2di)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccshi_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacssdqh((__v4si)__A, (__v4si)__B, (__v2di)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_macchi_epi32(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmacsdqh((__v4si)__A, (__v4si)__B, (__v2di)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maddsd_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmadcsswd((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maddd_epi16(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpmadcswd((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddw_epi8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddbw((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddd_epi8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddbd((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epi8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddbq((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddd_epi16(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddwd((__v8hi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epi16(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddwq((__v8hi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epi32(__m128i __A)
{
return (__m128i)__builtin_ia32_vphadddq((__v4si)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddw_epu8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddubw((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddd_epu8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddubd((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epu8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddubq((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddd_epu16(__m128i __A)
{
return (__m128i)__builtin_ia32_vphadduwd((__v8hi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epu16(__m128i __A)
{
return (__m128i)__builtin_ia32_vphadduwq((__v8hi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_haddq_epu32(__m128i __A)
{
return (__m128i)__builtin_ia32_vphaddudq((__v4si)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsubw_epi8(__m128i __A)
{
return (__m128i)__builtin_ia32_vphsubbw((__v16qi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsubd_epi16(__m128i __A)
{
return (__m128i)__builtin_ia32_vphsubwd((__v8hi)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hsubq_epi32(__m128i __A)
{
return (__m128i)__builtin_ia32_vphsubdq((__v4si)__A);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmov_si128(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpcmov(__A, __B, __C);
}
-static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmov_si256(__m256i __A, __m256i __B, __m256i __C)
{
return (__m256i)__builtin_ia32_vpcmov_256(__A, __B, __C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_perm_epi8(__m128i __A, __m128i __B, __m128i __C)
{
return (__m128i)__builtin_ia32_vpperm((__v16qi)__A, (__v16qi)__B, (__v16qi)__C);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_rot_epi8(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vprotb((__v16qi)__A, (__v16qi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_rot_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vprotw((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_rot_epi32(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vprotd((__v4si)__A, (__v4si)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_rot_epi64(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vprotq((__v2di)__A, (__v2di)__B);
@@ -254,49 +257,49 @@ _mm_rot_epi64(__m128i __A, __m128i __B)
__m128i __A = (A); \
(__m128i)__builtin_ia32_vprotqi((__v2di)__A, (N)); })
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi8(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshlb((__v16qi)__A, (__v16qi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshlw((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi32(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshld((__v4si)__A, (__v4si)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi64(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshlq((__v2di)__A, (__v2di)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha_epi8(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshab((__v16qi)__A, (__v16qi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha_epi16(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshaw((__v8hi)__A, (__v8hi)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha_epi32(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshad((__v4si)__A, (__v4si)__B);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha_epi64(__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_vpshaq((__v2di)__A, (__v2di)__B);
@@ -351,385 +354,385 @@ _mm_sha_epi64(__m128i __A, __m128i __B)
#define _MM_PCOMCTRL_FALSE 6
#define _MM_PCOMCTRL_TRUE 7
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epu8(__m128i __A, __m128i __B)
{
return _mm_com_epu8(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epu16(__m128i __A, __m128i __B)
{
return _mm_com_epu16(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epu32(__m128i __A, __m128i __B)
{
return _mm_com_epu32(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epu64(__m128i __A, __m128i __B)
{
return _mm_com_epu64(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epi8(__m128i __A, __m128i __B)
{
return _mm_com_epi8(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epi16(__m128i __A, __m128i __B)
{
return _mm_com_epi16(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epi32(__m128i __A, __m128i __B)
{
return _mm_com_epi32(__A, __B, _MM_PCOMCTRL_TRUE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comlt_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_LT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comle_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_LE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comgt_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_GT);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comge_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_GE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comeq_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_EQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comneq_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_NEQ);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comfalse_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_FALSE);
}
-static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_comtrue_epi64(__m128i __A, __m128i __B)
{
return _mm_com_epi64(__A, __B, _MM_PCOMCTRL_TRUE);
@@ -763,42 +766,44 @@ _mm_comtrue_epi64(__m128i __A, __m128i __B)
(__m256)__builtin_ia32_vpermil2ps256((__v8sf)__X, (__v8sf)__Y, \
(__v8si)__C, (I)); })
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_frcz_ss(__m128 __A)
{
return (__m128)__builtin_ia32_vfrczss((__v4sf)__A);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_frcz_sd(__m128d __A)
{
return (__m128d)__builtin_ia32_vfrczsd((__v2df)__A);
}
-static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_frcz_ps(__m128 __A)
{
return (__m128)__builtin_ia32_vfrczps((__v4sf)__A);
}
-static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_frcz_pd(__m128d __A)
{
return (__m128d)__builtin_ia32_vfrczpd((__v2df)__A);
}
-static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_frcz_ps(__m256 __A)
{
return (__m256)__builtin_ia32_vfrczps256((__v8sf)__A);
}
-static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))
+static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_frcz_pd(__m256d __A)
{
return (__m256d)__builtin_ia32_vfrczpd256((__v4df)__A);
}
+#undef __DEFAULT_FN_ATTRS
+
#endif /* __XOP__ */
#endif /* __XOPINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h b/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h
new file mode 100644
index 0000000..9d3378f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xtestintrin.h
@@ -0,0 +1,41 @@
+/*===---- xtestintrin.h - XTEST intrinsic ---------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <xtestintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __XTESTINTRIN_H
+#define __XTESTINTRIN_H
+
+/* xtest returns non-zero if the instruction is executed within an RTM or active
+ * HLE region. */
+/* FIXME: This can be an either or for RTM/HLE. Deal with this when HLE is
+ * supported. */
+static __inline__ int
+ __attribute__((__always_inline__, __nodebug__, __target__("rtm")))
+ _xtest(void) {
+ return __builtin_ia32_xtest();
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
index 080a4ad..b884214 100644
--- a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
+++ b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
@@ -44,8 +44,6 @@ public:
Diagnostics->setClient(new IgnoringDiagConsumer, true);
}
- ~SimpleFormatContext() { }
-
FileID createInMemoryFile(StringRef Name, StringRef Content) {
std::unique_ptr<llvm::MemoryBuffer> Source =
llvm::MemoryBuffer::getMemBuffer(Content);
diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
index baa166e..8cdd283 100644
--- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
@@ -847,7 +847,7 @@ bool clang::index::generateUSRForDecl(const Decl *D,
return UG.ignoreResults();
}
-bool clang::index::generateUSRForMacro(const MacroDefinition *MD,
+bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
const SourceManager &SM,
SmallVectorImpl<char> &Buf) {
// Don't generate USRs for things with invalid locations.
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
index d6b255f..b805990 100644
--- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
@@ -14,10 +14,12 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
@@ -32,9 +34,13 @@
using namespace clang;
const IdentifierInfo *
-HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
- if (ControllingMacro)
+HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
+ if (ControllingMacro) {
+ if (ControllingMacro->isOutOfDate())
+ External->updateOutOfDateIdentifier(
+ *const_cast<IdentifierInfo *>(ControllingMacro));
return ControllingMacro;
+ }
if (!ControllingMacroID || !External)
return nullptr;
@@ -149,7 +155,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
SmallString<128> HashStr;
llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
- llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
+ llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");
}
return Result.str().str();
}
@@ -157,7 +163,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
// Look in the module map to determine if there is a module by this name.
Module *Module = ModMap.findModule(ModuleName);
- if (Module || !AllowSearch || !LangOpts.ModulesImplicitMaps)
+ if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
return Module;
// Look through the various header search paths to load any available module
@@ -297,7 +303,7 @@ const FileEntry *DirectoryLookup::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
- return getFileAndSuggestModule(HS, TmpDir.str(), getDir(),
+ return getFileAndSuggestModule(HS, TmpDir, getDir(),
isSystemHeaderDirectory(),
SuggestedModule);
}
@@ -438,7 +444,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
HS.IncrementFrameworkLookupCount();
// If the framework dir doesn't exist, we fail.
- const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
+ const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName);
if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
@@ -450,7 +456,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
if (getDirCharacteristic() == SrcMgr::C_User) {
SmallString<1024> SystemFrameworkMarker(FrameworkName);
SystemFrameworkMarker += ".system_framework";
- if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
+ if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
CacheEntry.IsUserSpecifiedSystemFramework = true;
}
}
@@ -476,7 +482,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
}
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
- const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
+ const FileEntry *FE = FileMgr.getFile(FrameworkName,
/*openFile=*/!SuggestedModule);
if (!FE) {
// Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
@@ -487,7 +493,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
Private+strlen(Private));
- FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule);
+ FE = FileMgr.getFile(FrameworkName, /*openFile=*/!SuggestedModule);
}
// If we found the header and are allowed to suggest a module, do so now.
@@ -526,9 +532,13 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// Load this framework module. If that succeeds, find the suggested module
// for this header, if any.
bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
- if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
- *SuggestedModule = HS.findModuleForHeader(FE);
- }
+ HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem);
+
+ // FIXME: This can find a module not part of ModuleName, which is
+ // important so that we're consistent about whether this header
+ // corresponds to a module. Possibly we should lock down framework modules
+ // so that this is not possible.
+ *SuggestedModule = HS.findModuleForHeader(FE);
} else {
*SuggestedModule = HS.findModuleForHeader(FE);
}
@@ -594,7 +604,13 @@ const FileEntry *HeaderSearch::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
// Otherwise, just return the file.
- return FileMgr.getFile(Filename, /*openFile=*/true);
+ const FileEntry *File = FileMgr.getFile(Filename, /*openFile=*/true);
+ if (File && SuggestedModule) {
+ // If there is a module that corresponds to this header, suggest it.
+ hasModuleMap(Filename, File->getDir(), /*SystemHeaderDir*/false);
+ *SuggestedModule = findModuleForHeader(File);
+ }
+ return File;
}
// This is the header that MSVC's header search would have found.
@@ -628,7 +644,7 @@ const FileEntry *HeaderSearch::LookupFile(
bool IncluderIsSystemHeader =
Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
if (const FileEntry *FE = getFileAndSuggestModule(
- *this, TmpDir.str(), IncluderAndDir.second,
+ *this, TmpDir, IncluderAndDir.second,
IncluderIsSystemHeader, SuggestedModule)) {
if (!Includer) {
assert(First && "only first includer can have no file");
@@ -865,7 +881,7 @@ LookupSubframeworkHeader(StringRef Filename,
++NumSubFrameworkLookups;
// If the framework dir doesn't exist, we fail.
- const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
+ const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName);
if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
@@ -890,7 +906,7 @@ LookupSubframeworkHeader(StringRef Filename,
}
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
- if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) {
+ if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true))) {
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
@@ -902,7 +918,7 @@ LookupSubframeworkHeader(StringRef Filename,
}
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
- if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true)))
+ if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true)))
return nullptr;
}
@@ -979,7 +995,8 @@ HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
return HFI;
}
-bool HeaderSearch::tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const {
+bool HeaderSearch::tryGetFileInfo(const FileEntry *FE,
+ HeaderFileInfo &Result) const {
if (FE->getUID() >= FileInfo.size())
return false;
const HeaderFileInfo &HFI = FileInfo[FE->getUID()];
@@ -1012,11 +1029,13 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
HFI.isModuleHeader = true;
- HFI.isCompilingModuleHeader = isCompilingModuleHeader;
+ HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
HFI.setHeaderRole(Role);
}
-bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
+bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
+ const FileEntry *File,
+ bool isImport, Module *M) {
++NumIncluded; // Count # of attempted #includes.
// Get information about this file.
@@ -1040,11 +1059,16 @@ bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
// Next, check to see if the file is wrapped with #ifndef guards. If so, and
// if the macro that guards it is defined, we know the #include has no effect.
if (const IdentifierInfo *ControllingMacro
- = FileInfo.getControllingMacro(ExternalLookup))
- if (ControllingMacro->hasMacroDefinition()) {
+ = FileInfo.getControllingMacro(ExternalLookup)) {
+ // If the header corresponds to a module, check whether the macro is already
+ // defined in that module rather than checking in the current set of visible
+ // modules.
+ if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)
+ : PP.isMacroDefined(ControllingMacro)) {
++NumMultiIncludeFileOptzn;
return false;
}
+ }
// Increment the number of times this file has been included.
++FileInfo.NumIncludes;
@@ -1067,7 +1091,7 @@ StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
bool HeaderSearch::hasModuleMap(StringRef FileName,
const DirectoryEntry *Root,
bool IsSystem) {
- if (!enabledModules() || !LangOpts.ModulesImplicitMaps)
+ if (!HSOpts->ImplicitModuleMaps)
return false;
SmallVector<const DirectoryEntry *, 2> FixUpDirectories;
@@ -1194,7 +1218,7 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
const FileEntry *
HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) {
- if (!LangOpts.ModulesImplicitMaps)
+ if (!HSOpts->ImplicitModuleMaps)
return nullptr;
// For frameworks, the preferred spelling is Modules/module.modulemap, but
// module.map at the framework root is also accepted.
@@ -1220,6 +1244,9 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name,
// Try to load a module map file.
switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
case LMM_InvalidModuleMap:
+ // Try to infer a module map from the framework directory.
+ if (HSOpts->ImplicitModuleMaps)
+ ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);
break;
case LMM_AlreadyLoaded:
@@ -1227,15 +1254,10 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name,
return nullptr;
case LMM_NewlyLoaded:
- return ModMap.findModule(Name);
+ break;
}
-
- // Try to infer a module map from the framework directory.
- if (LangOpts.ModulesImplicitMaps)
- return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/nullptr);
-
- return nullptr;
+ return ModMap.findModule(Name);
}
@@ -1273,7 +1295,7 @@ HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem,
void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
Modules.clear();
- if (LangOpts.ModulesImplicitMaps) {
+ if (HSOpts->ImplicitModuleMaps) {
// Load module maps for each of the header search directories.
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
@@ -1284,7 +1306,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
DirNative);
// Search each of the ".framework" directories to load them as modules.
- for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
+ for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
if (llvm::sys::path::extension(Dir->path()) != ".framework")
continue;
@@ -1324,7 +1346,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
}
void HeaderSearch::loadTopLevelSystemModules() {
- if (!LangOpts.ModulesImplicitMaps)
+ if (!HSOpts->ImplicitModuleMaps)
return;
// Load module maps for each of the header search directories.
@@ -1342,7 +1364,7 @@ void HeaderSearch::loadTopLevelSystemModules() {
}
void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
- assert(LangOpts.ModulesImplicitMaps &&
+ assert(HSOpts->ImplicitModuleMaps &&
"Should not be loading subdirectory module maps");
if (SearchDir.haveSearchedAllModuleMaps())
@@ -1351,10 +1373,12 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative);
- for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
+ for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
- SearchDir.isFramework());
+ bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
+ if (IsFramework == SearchDir.isFramework())
+ loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
+ SearchDir.isFramework());
}
SearchDir.setSearchedAllModuleMaps(true);
diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
index ca5252e..4007914 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
@@ -143,14 +143,8 @@ Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts,
/// range will outlive it, so it doesn't take ownership of it.
Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
const SourceManager &SM, const LangOptions &langOpts)
- : FileLoc(SM.getLocForStartOfFile(FID)), LangOpts(langOpts) {
-
- InitLexer(FromFile->getBufferStart(), FromFile->getBufferStart(),
- FromFile->getBufferEnd());
-
- // We *are* in raw mode.
- LexingRawMode = true;
-}
+ : Lexer(SM.getLocForStartOfFile(FID), langOpts, FromFile->getBufferStart(),
+ FromFile->getBufferStart(), FromFile->getBufferEnd()) {}
/// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
/// _Pragma expansion. This has a variety of magic semantics that this method
@@ -205,7 +199,7 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc,
/// Stringify - Convert the specified string into a C string, with surrounding
/// ""'s, and with escaped \ and " characters.
-std::string Lexer::Stringify(const std::string &Str, bool Charify) {
+std::string Lexer::Stringify(StringRef Str, bool Charify) {
std::string Result = Str;
char Quote = Charify ? '\'' : '"';
for (unsigned i = 0, e = Result.size(); i != e; ++i) {
@@ -1860,7 +1854,7 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
char C = getAndAdvanceChar(CurPtr, Result);
while (C != '>') {
// Skip escaped characters.
- if (C == '\\') {
+ if (C == '\\' && CurPtr < BufferEnd) {
// Skip the escaped character.
getAndAdvanceChar(CurPtr, Result);
} else if (C == '\n' || C == '\r' || // Newline.
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
index 03331fb..aed9164 100644
--- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -144,7 +144,8 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
int CharVal = llvm::hexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
// About to shift out a digit?
- Overflow |= (ResultChar & 0xF0000000) ? true : false;
+ if (ResultChar & 0xF0000000)
+ Overflow = true;
ResultChar <<= 4;
ResultChar |= CharVal;
}
@@ -596,7 +597,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isFloat) break; // LF invalid.
// Check for long long. The L's need to be adjacent and the same case.
- if (s+1 != ThisTokEnd && s[1] == s[0]) {
+ if (s[1] == s[0]) {
+ assert(s + 1 < ThisTokEnd && "didn't maximally munch?");
if (isFPConstant) break; // long long invalid for floats.
isLongLong = true;
++s; // Eat both of them.
@@ -610,54 +612,45 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isLong || isLongLong || MicrosoftInteger)
break;
- // Allow i8, i16, i32, i64, and i128.
- if (s + 1 != ThisTokEnd) {
+ if (!isFPConstant) {
+ // Allow i8, i16, i32, i64, and i128.
switch (s[1]) {
- case '8':
- if (isFPConstant) break;
- s += 2; // i8 suffix
- MicrosoftInteger = 8;
- break;
- case '1':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '6') {
- s += 3; // i16 suffix
- MicrosoftInteger = 16;
- }
- else if (s[2] == '2') {
- if (s + 3 == ThisTokEnd) break;
- if (s[3] == '8') {
- s += 4; // i128 suffix
- MicrosoftInteger = 128;
- }
- }
- break;
- case '3':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '2') {
- s += 3; // i32 suffix
- MicrosoftInteger = 32;
- }
- break;
- case '6':
- if (isFPConstant) break;
- if (s + 2 == ThisTokEnd) break;
- if (s[2] == '4') {
- s += 3; // i64 suffix
- MicrosoftInteger = 64;
- }
- break;
- default:
- break;
- }
- if (MicrosoftInteger)
+ case '8':
+ s += 2; // i8 suffix
+ MicrosoftInteger = 8;
+ break;
+ case '1':
+ if (s[2] == '6') {
+ s += 3; // i16 suffix
+ MicrosoftInteger = 16;
+ } else if (s[2] == '2' && s[3] == '8') {
+ s += 4; // i128 suffix
+ MicrosoftInteger = 128;
+ }
+ break;
+ case '3':
+ if (s[2] == '2') {
+ s += 3; // i32 suffix
+ MicrosoftInteger = 32;
+ }
+ break;
+ case '6':
+ if (s[2] == '4') {
+ s += 3; // i64 suffix
+ MicrosoftInteger = 64;
+ }
break;
+ default:
+ break;
+ }
+ }
+ if (MicrosoftInteger) {
+ assert(s <= ThisTokEnd && "didn't maximally munch?");
+ break;
}
}
// "i", "if", and "il" are user-defined suffixes in C++1y.
- if (PP.getLangOpts().CPlusPlus14 && *s == 'i')
+ if (*s == 'i' && PP.getLangOpts().CPlusPlus14)
break;
// fall through.
case 'j':
@@ -755,11 +748,11 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
s++;
int c1 = s[0];
- int c2 = s[1];
// Handle a hex number like 0x1234.
- if ((c1 == 'x' || c1 == 'X') && (isHexDigit(c2) || c2 == '.')) {
+ if ((c1 == 'x' || c1 == 'X') && (isHexDigit(s[1]) || s[1] == '.')) {
s++;
+ assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 16;
DigitsBegin = s;
s = SkipHexDigits(s);
@@ -811,7 +804,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
}
// Handle simple binary numbers 0b01010
- if ((c1 == 'b' || c1 == 'B') && (c2 == '0' || c2 == '1')) {
+ if ((c1 == 'b' || c1 == 'B') && (s[1] == '0' || s[1] == '1')) {
// 0b101010 is a C++1y / GCC extension.
PP.Diag(TokLoc,
PP.getLangOpts().CPlusPlus14
@@ -820,6 +813,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
? diag::ext_binary_literal_cxx14
: diag::ext_binary_literal);
++s;
+ assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 2;
DigitsBegin = s;
s = SkipBinaryDigits(s);
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
index 9967f3f..1c1979d 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
@@ -133,12 +133,11 @@ bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok,
// If there are no identifiers in the argument list, or if the identifiers are
// known to not be macros, pre-expansion won't modify it.
for (; ArgTok->isNot(tok::eof); ++ArgTok)
- if (IdentifierInfo *II = ArgTok->getIdentifierInfo()) {
- if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled())
+ if (IdentifierInfo *II = ArgTok->getIdentifierInfo())
+ if (II->hasMacroDefinition())
// Return true even though the macro could be a function-like macro
- // without a following '(' token.
+ // without a following '(' token, or could be disabled, or not visible.
return true;
- }
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
index 5416886..109b6c1 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
@@ -218,13 +218,9 @@ void MacroDirective::dump() const {
if (auto *Prev = getPrevious())
Out << " prev " << Prev;
if (IsFromPCH) Out << " from_pch";
- if (IsImported) Out << " imported";
- if (IsAmbiguous) Out << " ambiguous";
- if (IsPublic)
- Out << " public";
- else if (isa<VisibilityMacroDirective>(this))
- Out << " private";
+ if (isa<VisibilityMacroDirective>(this))
+ Out << (IsPublic ? " public" : " private");
if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
if (auto *Info = DMD->getInfo()) {
@@ -234,3 +230,12 @@ void MacroDirective::dump() const {
}
Out << "\n";
}
+
+ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule,
+ IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides) {
+ void *Mem = PP.getPreprocessorAllocator().Allocate(
+ sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
+ llvm::alignOf<ModuleMacro>());
+ return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
index ef322d8..96d3e4b 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
@@ -89,7 +89,9 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
HeaderSearch &HeaderInfo)
: SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
- CompilingModule(nullptr), SourceModule(nullptr) {}
+ CompilingModule(nullptr), SourceModule(nullptr), NumCreatedModules(0) {
+ MMapLangOpts.LineComment = true;
+}
ModuleMap::~ModuleMap() {
for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
@@ -163,7 +165,8 @@ static bool isBuiltinHeader(StringRef FileName) {
ModuleMap::HeadersMap::iterator
ModuleMap::findKnownHeader(const FileEntry *File) {
HeadersMap::iterator Known = Headers.find(File);
- if (Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
+ if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
+ Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
HeaderInfo.loadTopLevelSystemModules();
return Headers.find(File);
@@ -174,6 +177,9 @@ ModuleMap::findKnownHeader(const FileEntry *File) {
ModuleMap::KnownHeader
ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
+ if (UmbrellaDirs.empty())
+ return KnownHeader();
+
const DirectoryEntry *Dir = File->getDir();
assert(Dir && "file in no directory");
@@ -203,35 +209,32 @@ ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
return KnownHeader();
}
-// Returns true if RequestingModule directly uses RequestedModule.
-static bool directlyUses(const Module *RequestingModule,
- const Module *RequestedModule) {
- return std::find(RequestingModule->DirectUses.begin(),
- RequestingModule->DirectUses.end(),
- RequestedModule) != RequestingModule->DirectUses.end();
-}
-
static bool violatesPrivateInclude(Module *RequestingModule,
const FileEntry *IncFileEnt,
ModuleMap::ModuleHeaderRole Role,
Module *RequestedModule) {
bool IsPrivateRole = Role & ModuleMap::PrivateHeader;
#ifndef NDEBUG
- // Check for consistency between the module header role
- // as obtained from the lookup and as obtained from the module.
- // This check is not cheap, so enable it only for debugging.
- bool IsPrivate = false;
- SmallVectorImpl<Module::Header> *HeaderList[] =
- {&RequestedModule->Headers[Module::HK_Private],
- &RequestedModule->Headers[Module::HK_PrivateTextual]};
- for (auto *Hdrs : HeaderList)
- IsPrivate |=
- std::find_if(Hdrs->begin(), Hdrs->end(), [&](const Module::Header &H) {
- return H.Entry == IncFileEnt;
- }) != Hdrs->end();
- assert(IsPrivate == IsPrivateRole && "inconsistent headers and roles");
+ if (IsPrivateRole) {
+ // Check for consistency between the module header role
+ // as obtained from the lookup and as obtained from the module.
+ // This check is not cheap, so enable it only for debugging.
+ bool IsPrivate = false;
+ SmallVectorImpl<Module::Header> *HeaderList[] = {
+ &RequestedModule->Headers[Module::HK_Private],
+ &RequestedModule->Headers[Module::HK_PrivateTextual]};
+ for (auto *Hs : HeaderList)
+ IsPrivate |=
+ std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
+ return H.Entry == IncFileEnt;
+ }) != Hs->end();
+ assert((!IsPrivateRole || IsPrivate) && "inconsistent headers and roles");
+ }
#endif
return IsPrivateRole &&
+ // FIXME: Should we map RequestingModule to its top-level module here
+ // too? This check is redundant with the isSubModuleOf check in
+ // diagnoseHeaderInclusion.
RequestedModule->getTopLevelModule() != RequestingModule;
}
@@ -259,7 +262,8 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
if (Known != Headers.end()) {
for (const KnownHeader &Header : Known->second) {
// If 'File' is part of 'RequestingModule' we can definitely include it.
- if (Header.getModule() == RequestingModule)
+ if (Header.getModule() &&
+ Header.getModule()->isSubModuleOf(RequestingModule))
return;
// Remember private headers for later printing of a diagnostic.
@@ -272,7 +276,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// If uses need to be specified explicitly, we are only allowed to return
// modules that are explicitly used by the requesting module.
if (RequestingModule && LangOpts.ModulesDeclUse &&
- !directlyUses(RequestingModule, Header.getModule())) {
+ !RequestingModule->directlyUses(Header.getModule())) {
NotUsed = Header.getModule();
continue;
}
@@ -286,14 +290,14 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// We have found a header, but it is private.
if (Private) {
- Diags.Report(FilenameLoc, diag::error_use_of_private_header_outside_module)
+ Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
<< Filename;
return;
}
// We have found a module, but we don't use it.
if (NotUsed) {
- Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+ Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
<< RequestingModule->getFullModuleName() << Filename;
return;
}
@@ -304,7 +308,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// At this point, only non-modular includes remain.
if (LangOpts.ModulesStrictDeclUse) {
- Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+ Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
<< RequestingModule->getFullModuleName() << Filename;
} else if (RequestingModule) {
diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
@@ -314,43 +318,42 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
}
}
-ModuleMap::KnownHeader
-ModuleMap::findModuleForHeader(const FileEntry *File,
- Module *RequestingModule,
- bool IncludeTextualHeaders) {
- HeadersMap::iterator Known = findKnownHeader(File);
+static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
+ const ModuleMap::KnownHeader &Old) {
+ // Prefer a public header over a private header.
+ if ((New.getRole() & ModuleMap::PrivateHeader) !=
+ (Old.getRole() & ModuleMap::PrivateHeader))
+ return !(New.getRole() & ModuleMap::PrivateHeader);
+
+ // Prefer a non-textual header over a textual header.
+ if ((New.getRole() & ModuleMap::TextualHeader) !=
+ (Old.getRole() & ModuleMap::TextualHeader))
+ return !(New.getRole() & ModuleMap::TextualHeader);
+
+ // Don't have a reason to choose between these. Just keep the first one.
+ return false;
+}
+ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
- if (!IncludeTextualHeaders && (R.getRole() & ModuleMap::TextualHeader))
+ if (R.getRole() & ModuleMap::TextualHeader)
return ModuleMap::KnownHeader();
return R;
};
+ HeadersMap::iterator Known = findKnownHeader(File);
if (Known != Headers.end()) {
ModuleMap::KnownHeader Result;
-
// Iterate over all modules that 'File' is part of to find the best fit.
- for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
- E = Known->second.end();
- I != E; ++I) {
+ for (KnownHeader &H : Known->second) {
+ // Prefer a header from the current module over all others.
+ if (H.getModule()->getTopLevelModule() == CompilingModule)
+ return MakeResult(H);
// Cannot use a module if it is unavailable.
- if (!I->getModule()->isAvailable())
+ if (!H.getModule()->isAvailable())
continue;
-
- // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
- // module we are looking for.
- if (I->getModule() == RequestingModule)
- return MakeResult(*I);
-
- // If uses need to be specified explicitly, we are only allowed to return
- // modules that are explicitly used by the requesting module.
- if (RequestingModule && LangOpts.ModulesDeclUse &&
- !directlyUses(RequestingModule, I->getModule()))
- continue;
-
- // Prefer a public header over a private header.
- if (!Result || (Result.getRole() & ModuleMap::PrivateHeader))
- Result = *I;
+ if (!Result || isBetterKnownHeader(H, Result))
+ Result = H;
}
return MakeResult(Result);
}
@@ -548,7 +551,7 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent,
- IsFramework, IsExplicit);
+ IsFramework, IsExplicit, NumCreatedModules++);
if (LangOpts.CurrentModule == Name) {
SourceModule = Result;
SourceModuleName = Name;
@@ -580,19 +583,28 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
}
}
-Module *
-ModuleMap::inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
- bool IsSystem,
- Module *Parent) {
+Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ bool IsSystem, Module *Parent) {
Attributes Attrs;
Attrs.IsSystem = IsSystem;
- return inferFrameworkModule(ModuleName, FrameworkDir, Attrs, Parent);
+ return inferFrameworkModule(FrameworkDir, Attrs, Parent);
}
-Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
+Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Attributes Attrs, Module *Parent) {
+ // Note: as an egregious but useful hack we use the real path here, because
+ // we might be looking at an embedded framework that symlinks out to a
+ // top-level framework, and we need to infer as if we were naming the
+ // top-level framework.
+ StringRef FrameworkDirName =
+ SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
+
+ // In case this is a case-insensitive filesystem, use the canonical
+ // directory name as the ModuleName, since modules are case-sensitive.
+ // FIXME: we should be able to give a fix-it hint for the correct spelling.
+ SmallString<32> ModuleNameStorage;
+ StringRef ModuleName = sanitizeFilenameAsIdentifier(
+ llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
// Check whether we've already found this module.
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
@@ -605,20 +617,6 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
const FileEntry *ModuleMapFile = nullptr;
if (!Parent) {
// Determine whether we're allowed to infer a module map.
-
- // Note: as an egregious but useful hack we use the real path here, because
- // we might be looking at an embedded framework that symlinks out to a
- // top-level framework, and we need to infer as if we were naming the
- // top-level framework.
- StringRef FrameworkDirName
- = SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
-
- // In case this is a case-insensitive filesystem, make sure the canonical
- // directory name matches ModuleName exactly. Modules are case-sensitive.
- // FIXME: we should be able to give a fix-it hint for the correct spelling.
- if (llvm::sys::path::stem(FrameworkDirName) != ModuleName)
- return nullptr;
-
bool canInfer = false;
if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
// Figure out the parent path.
@@ -678,7 +676,8 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
return nullptr;
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
- /*IsFramework=*/true, /*IsExplicit=*/false);
+ /*IsFramework=*/true, /*IsExplicit=*/false,
+ NumCreatedModules++);
InferredModuleAllowedBy[Result] = ModuleMapFile;
Result->IsInferred = true;
if (LangOpts.CurrentModule == ModuleName) {
@@ -689,14 +688,16 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
Result->IsSystem |= Attrs.IsSystem;
Result->IsExternC |= Attrs.IsExternC;
Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
+ Result->Directory = FrameworkDir;
if (!Parent)
Modules[ModuleName] = Result;
// umbrella header "umbrella-header-name"
- Result->Umbrella = UmbrellaHeader;
- Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader));
- UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
+ //
+ // The "Headers/" component of the name is implied because this is
+ // a framework module.
+ setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
// export *
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
@@ -711,8 +712,7 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
= StringRef(FrameworkDir->getName());
llvm::sys::path::append(SubframeworksDirName, "Frameworks");
llvm::sys::path::native(SubframeworksDirName);
- for (llvm::sys::fs::directory_iterator
- Dir(SubframeworksDirName.str(), EC), DirEnd;
+ for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
if (!StringRef(Dir->path()).endswith(".framework"))
continue;
@@ -742,10 +742,7 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
continue;
// FIXME: Do we want to warn about subframeworks without umbrella headers?
- SmallString<32> NameBuf;
- inferFrameworkModule(sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(Dir->path()), NameBuf),
- SubframeworkDir, Attrs, Result);
+ inferFrameworkModule(SubframeworkDir, Attrs, Result);
}
}
@@ -758,14 +755,18 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
return Result;
}
-void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
+void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
+ Twine NameAsWritten) {
Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
Mod->Umbrella = UmbrellaHeader;
+ Mod->UmbrellaAsWritten = NameAsWritten.str();
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
}
-void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
+void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+ Twine NameAsWritten) {
Mod->Umbrella = UmbrellaDir;
+ Mod->UmbrellaAsWritten = NameAsWritten.str();
UmbrellaDirs[UmbrellaDir] = Mod;
}
@@ -850,50 +851,44 @@ void ModuleMap::dump() {
}
bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
- bool HadError = false;
- for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
- Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
- Complain);
+ auto Unresolved = std::move(Mod->UnresolvedExports);
+ Mod->UnresolvedExports.clear();
+ for (auto &UE : Unresolved) {
+ Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
if (Export.getPointer() || Export.getInt())
Mod->Exports.push_back(Export);
else
- HadError = true;
+ Mod->UnresolvedExports.push_back(UE);
}
- Mod->UnresolvedExports.clear();
- return HadError;
+ return !Mod->UnresolvedExports.empty();
}
bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
- bool HadError = false;
- for (unsigned I = 0, N = Mod->UnresolvedDirectUses.size(); I != N; ++I) {
- Module *DirectUse =
- resolveModuleId(Mod->UnresolvedDirectUses[I], Mod, Complain);
+ auto Unresolved = std::move(Mod->UnresolvedDirectUses);
+ Mod->UnresolvedDirectUses.clear();
+ for (auto &UDU : Unresolved) {
+ Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
if (DirectUse)
Mod->DirectUses.push_back(DirectUse);
else
- HadError = true;
+ Mod->UnresolvedDirectUses.push_back(UDU);
}
- Mod->UnresolvedDirectUses.clear();
- return HadError;
+ return !Mod->UnresolvedDirectUses.empty();
}
bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
- bool HadError = false;
- for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
- Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
- Mod, Complain);
- if (!OtherMod) {
- HadError = true;
- continue;
- }
-
- Module::Conflict Conflict;
- Conflict.Other = OtherMod;
- Conflict.Message = Mod->UnresolvedConflicts[I].Message;
- Mod->Conflicts.push_back(Conflict);
- }
+ auto Unresolved = std::move(Mod->UnresolvedConflicts);
Mod->UnresolvedConflicts.clear();
- return HadError;
+ for (auto &UC : Unresolved) {
+ if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
+ Module::Conflict Conflict;
+ Conflict.Other = OtherMod;
+ Conflict.Message = UC.Message;
+ Mod->Conflicts.push_back(Conflict);
+ } else
+ Mod->UnresolvedConflicts.push_back(UC);
+ }
+ return !Mod->UnresolvedConflicts.empty();
}
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
@@ -1533,7 +1528,7 @@ void ModuleMapParser::parseModuleDecl() {
/// 'extern' 'module' module-id string-literal
void ModuleMapParser::parseExternModuleDecl() {
assert(Tok.is(MMToken::ExternKeyword));
- consumeToken(); // 'extern' keyword
+ SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
// Parse 'module' keyword.
if (!Tok.is(MMToken::ModuleKeyword)) {
@@ -1565,14 +1560,14 @@ void ModuleMapParser::parseExternModuleDecl() {
if (llvm::sys::path::is_relative(FileNameRef)) {
ModuleMapFileName += Directory->getName();
llvm::sys::path::append(ModuleMapFileName, FileName);
- FileNameRef = ModuleMapFileName.str();
+ FileNameRef = ModuleMapFileName;
}
if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
Map.parseModuleMapFile(
File, /*IsSystem=*/false,
Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
? Directory
- : File->getDir());
+ : File->getDir(), ExternLoc);
}
/// \brief Parse a requires declaration.
@@ -1712,7 +1707,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// Check whether this file is in the public headers.
llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
- llvm::sys::path::append(FullPathName, RelativePathName.str());
+ llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
if (!File) {
@@ -1722,13 +1717,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
FullPathName.resize(FullPathLength);
llvm::sys::path::append(RelativePathName, "PrivateHeaders",
Header.FileName);
- llvm::sys::path::append(FullPathName, RelativePathName.str());
+ llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
}
} else {
// Lookup for normal headers.
llvm::sys::path::append(RelativePathName, Header.FileName);
- llvm::sys::path::append(FullPathName, RelativePathName.str());
+ llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
// If this is a system module with a top-level header, this header
@@ -1744,7 +1739,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// If Clang supplies this header but the underlying system does not,
// just silently swap in our builtin version. Otherwise, we'll end
// up adding both (later).
- if (!File && BuiltinFile) {
+ //
+ // For local visibility, entirely replace the system file with our
+ // one and textually include the system one. We need to pass macros
+ // from our header to the system one if we #include_next it.
+ //
+ // FIXME: Can we do this in all cases?
+ if (BuiltinFile && (!File || Map.LangOpts.ModulesLocalVisibility)) {
File = BuiltinFile;
RelativePathName = BuiltinPathName;
BuiltinFile = nullptr;
@@ -1764,7 +1765,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
HadError = true;
} else {
// Record this umbrella header.
- Map.setUmbrellaHeader(ActiveModule, File);
+ Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str());
}
} else if (LeadingToken == MMToken::ExcludeKeyword) {
Module::Header H = {RelativePathName.str(), File};
@@ -1846,7 +1847,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
}
// Record this umbrella directory.
- Map.setUmbrellaDir(ActiveModule, Dir);
+ Map.setUmbrellaDir(ActiveModule, Dir, DirName);
}
/// \brief Parse a module export declaration.
@@ -1897,18 +1898,21 @@ void ModuleMapParser::parseExportDecl() {
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module uses declaration.
+/// \brief Parse a module use declaration.
///
-/// uses-declaration:
-/// 'uses' wildcard-module-id
+/// use-declaration:
+/// 'use' wildcard-module-id
void ModuleMapParser::parseUseDecl() {
assert(Tok.is(MMToken::UseKeyword));
- consumeToken();
+ auto KWLoc = consumeToken();
// Parse the module-id.
ModuleId ParsedModuleId;
parseModuleId(ParsedModuleId);
- ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
+ if (ActiveModule->Parent)
+ Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
+ else
+ ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
}
/// \brief Parse a link declaration.
@@ -2315,7 +2319,8 @@ bool ModuleMapParser::parseModuleMapFile() {
}
bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *Dir) {
+ const DirectoryEntry *Dir,
+ SourceLocation ExternModuleLoc) {
llvm::DenseMap<const FileEntry *, bool>::iterator Known
= ParsedModuleMap.find(File);
if (Known != ParsedModuleMap.end())
@@ -2323,7 +2328,7 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
assert(Target && "Missing target information");
auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
- FileID ID = SourceMgr.createFileID(File, SourceLocation(), FileCharacter);
+ FileID ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
if (!Buffer)
return ParsedModuleMap[File] = true;
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
index 99b87a0..12a7784 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
@@ -84,14 +84,14 @@ void PPConditionalDirectiveRecord::If(SourceLocation Loc,
void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
const Token &MacroNameTok,
- const MacroDirective *MD) {
+ const MacroDefinition &MD) {
addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
CondDirectiveStack.push_back(Loc);
}
void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
const Token &MacroNameTok,
- const MacroDirective *MD) {
+ const MacroDefinition &MD) {
addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
CondDirectiveStack.push_back(Loc);
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index bf0ce72..ce64538 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -62,26 +62,14 @@ MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L,
return MI;
}
-DefMacroDirective *
-Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc,
- unsigned ImportedFromModuleID,
- ArrayRef<unsigned> Overrides) {
- unsigned NumExtra = (ImportedFromModuleID ? 1 : 0) + Overrides.size();
- return new (BP.Allocate(sizeof(DefMacroDirective) +
- sizeof(unsigned) * NumExtra,
- llvm::alignOf<DefMacroDirective>()))
- DefMacroDirective(MI, Loc, ImportedFromModuleID, Overrides);
+DefMacroDirective *Preprocessor::AllocateDefMacroDirective(MacroInfo *MI,
+ SourceLocation Loc) {
+ return new (BP) DefMacroDirective(MI, Loc);
}
UndefMacroDirective *
-Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc,
- unsigned ImportedFromModuleID,
- ArrayRef<unsigned> Overrides) {
- unsigned NumExtra = (ImportedFromModuleID ? 1 : 0) + Overrides.size();
- return new (BP.Allocate(sizeof(UndefMacroDirective) +
- sizeof(unsigned) * NumExtra,
- llvm::alignOf<UndefMacroDirective>()))
- UndefMacroDirective(UndefLoc, ImportedFromModuleID, Overrides);
+Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) {
+ return new (BP) UndefMacroDirective(UndefLoc);
}
VisibilityMacroDirective *
@@ -182,11 +170,13 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
return Diag(MacroNameTok, diag::err_defined_macro_name);
}
- if (isDefineUndef == MU_Undef && II->hasMacroDefinition() &&
- getMacroInfo(II)->isBuiltinMacro()) {
- // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
- // and C++ [cpp.predefined]p4], but allow it as an extension.
- Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+ if (isDefineUndef == MU_Undef) {
+ auto *MI = getMacroInfo(II);
+ if (MI && MI->isBuiltinMacro()) {
+ // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
+ // and C++ [cpp.predefined]p4], but allow it as an extension.
+ Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+ }
}
// If defining/undefining reserved identifier or a keyword, we need to issue
@@ -585,16 +575,16 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
}
}
-Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
+Module *Preprocessor::getModuleForLocation(SourceLocation Loc) {
ModuleMap &ModMap = HeaderInfo.getModuleMap();
- if (SourceMgr.isInMainFile(FilenameLoc)) {
+ if (SourceMgr.isInMainFile(Loc)) {
if (Module *CurMod = getCurrentModule())
return CurMod; // Compiling a module.
return HeaderInfo.getModuleMap().SourceModule; // Compiling a source.
}
// Try to determine the module of the include directive.
// FIXME: Look into directly passing the FileEntry from LookupFile instead.
- FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(FilenameLoc));
+ FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc));
if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) {
// The include comes from a file.
return ModMap.findModuleForHeader(EntryOfIncl).getModule();
@@ -605,6 +595,11 @@ Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
}
}
+Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) {
+ return HeaderInfo.getModuleMap().inferModuleFromLocation(
+ FullSourceLoc(Loc, SourceMgr));
+}
+
const FileEntry *Preprocessor::LookupFile(
SourceLocation FilenameLoc,
StringRef Filename,
@@ -1233,7 +1228,7 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
// Find the first non-whitespace character, so that we can make the
// diagnostic more succinct.
- StringRef Msg = Message.str().ltrim(" ");
+ StringRef Msg = StringRef(Message).ltrim(" ");
if (isWarning)
Diag(Tok, diag::pp_hash_warning) << Msg;
@@ -1290,7 +1285,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
// Okay, we finally have a valid identifier to undef.
- MacroDirective *MD = getMacroDirective(II);
+ MacroDirective *MD = getLocalMacroDirective(II);
// If the macro is not defined, this is an error.
if (!MD) {
@@ -1317,7 +1312,7 @@ void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
// Okay, we finally have a valid identifier to undef.
- MacroDirective *MD = getMacroDirective(II);
+ MacroDirective *MD = getLocalMacroDirective(II);
// If the macro is not defined, this is an error.
if (!MD) {
@@ -1444,6 +1439,8 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
static void EnterAnnotationToken(Preprocessor &PP,
SourceLocation Begin, SourceLocation End,
tok::TokenKind Kind, void *AnnotationVal) {
+ // FIXME: Produce this as the current token directly, rather than
+ // allocating a new token for it.
Token *Tok = new Token[1];
Tok[0].startToken();
Tok[0].setKind(Kind);
@@ -1453,6 +1450,51 @@ static void EnterAnnotationToken(Preprocessor &PP,
PP.EnterTokenStream(Tok, 1, true, true);
}
+/// \brief Produce a diagnostic informing the user that a #include or similar
+/// was implicitly treated as a module import.
+static void diagnoseAutoModuleImport(
+ Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
+ ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
+ SourceLocation PathEnd) {
+ assert(PP.getLangOpts().ObjC2 && "no import syntax available");
+
+ SmallString<128> PathString;
+ for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+ if (I)
+ PathString += '.';
+ PathString += Path[I].first->getName();
+ }
+ int IncludeKind = 0;
+
+ switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
+ case tok::pp_include:
+ IncludeKind = 0;
+ break;
+
+ case tok::pp_import:
+ IncludeKind = 1;
+ break;
+
+ case tok::pp_include_next:
+ IncludeKind = 2;
+ break;
+
+ case tok::pp___include_macros:
+ IncludeKind = 3;
+ break;
+
+ default:
+ llvm_unreachable("unknown include directive kind");
+ }
+
+ CharSourceRange ReplaceRange(SourceRange(HashLoc, PathEnd),
+ /*IsTokenRange=*/false);
+ PP.Diag(HashLoc, diag::warn_auto_module_import)
+ << IncludeKind << PathString
+ << FixItHint::CreateReplacement(ReplaceRange,
+ ("@import " + PathString + ";").str());
+}
+
/// HandleIncludeDirective - The "\#include" tokens have just been read, read
/// the file to be included from the lexer, then include it! This is a common
/// routine with functionality shared between \#include, \#include_next and
@@ -1491,7 +1533,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameBuffer.push_back('<');
if (ConcatenateIncludeName(FilenameBuffer, End))
return; // Found <eod> but no ">"? Diagnostic already emitted.
- Filename = FilenameBuffer.str();
+ Filename = FilenameBuffer;
CharEnd = End.getLocWithOffset(1);
break;
default:
@@ -1533,6 +1575,15 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
PragmaARCCFCodeAuditedLoc = SourceLocation();
}
+ // Complain about attempts to #include files in an assume-nonnull pragma.
+ if (PragmaAssumeNonNullLoc.isValid()) {
+ Diag(HashLoc, diag::err_pp_include_in_assume_nonnull);
+ Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
+
+ // Immediately leave the pragma.
+ PragmaAssumeNonNullLoc = SourceLocation();
+ }
+
if (HeaderInfo.HasIncludeAliasMap()) {
// Map the filename with the brackets still attached. If the name doesn't
// map to anything, fall back on the filename we've already gotten the
@@ -1561,10 +1612,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
isAngled, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : nullptr);
+ &SuggestedModule);
- if (Callbacks) {
- if (!File) {
+ if (!File) {
+ if (Callbacks) {
// Give the clients a chance to recover.
SmallString<128> RecoveryPath;
if (Callbacks->FileNotFound(Filename, RecoveryPath)) {
@@ -1578,24 +1629,11 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
- : nullptr,
- /*SkipCache*/ true);
+ &SuggestedModule, /*SkipCache*/ true);
}
}
}
-
- if (!SuggestedModule || !getLangOpts().Modules) {
- // Notify the callback object that we've seen an inclusion directive.
- Callbacks->InclusionDirective(HashLoc, IncludeTok,
- LangOpts.MSVCCompat ? NormalizedPath.c_str()
- : Filename,
- isAngled, FilenameRange, File, SearchPath,
- RelativePath, /*ImportedModule=*/nullptr);
- }
- }
- if (!File) {
if (!SuppressIncludeNotFoundError) {
// If the file could not be located and it was included via angle
// brackets, we can attempt a lookup as though it were a quoted path to
@@ -1607,8 +1645,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr,
Callbacks ? &RelativePath : nullptr,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
- : nullptr);
+ &SuggestedModule);
if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd);
Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) <<
@@ -1616,19 +1653,27 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\"");
}
}
+
// If the file is still not found, just go with the vanilla diagnostic
if (!File)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
}
- if (!File)
- return;
}
- // If we are supposed to import a module rather than including the header,
- // do so now.
- if (SuggestedModule && getLangOpts().Modules &&
+ // Should we enter the source file? Set to false if either the source file is
+ // known to have no effect beyond its effect on module visibility -- that is,
+ // if it's got an include guard that is already defined or is a modular header
+ // we've imported or already built.
+ bool ShouldEnter = true;
+
+ // Determine whether we should try to import the module for this #include, if
+ // there is one. Don't do so if precompiled module support is disabled or we
+ // are processing this module textually (because we're building the module).
+ if (File && SuggestedModule && getLangOpts().Modules &&
+ SuggestedModule.getModule()->getTopLevelModuleName() !=
+ getLangOpts().CurrentModule &&
SuggestedModule.getModule()->getTopLevelModuleName() !=
- getLangOpts().ImplementationOfModule) {
+ getLangOpts().ImplementationOfModule) {
// Compute the module access path corresponding to this module.
// FIXME: Should we have a second loadModule() overload to avoid this
// extra lookup step?
@@ -1639,111 +1684,57 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
std::reverse(Path.begin(), Path.end());
// Warn that we're replacing the include/import with a module import.
- SmallString<128> PathString;
- for (unsigned I = 0, N = Path.size(); I != N; ++I) {
- if (I)
- PathString += '.';
- PathString += Path[I].first->getName();
- }
- int IncludeKind = 0;
-
- switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
- case tok::pp_include:
- IncludeKind = 0;
- break;
-
- case tok::pp_import:
- IncludeKind = 1;
- break;
-
- case tok::pp_include_next:
- IncludeKind = 2;
- break;
-
- case tok::pp___include_macros:
- IncludeKind = 3;
- break;
-
- default:
- llvm_unreachable("unknown include directive kind");
- }
-
- // Determine whether we are actually building the module that this
- // include directive maps to.
- bool BuildingImportedModule
- = Path[0].first->getName() == getLangOpts().CurrentModule;
-
- if (!BuildingImportedModule && getLangOpts().ObjC2) {
- // If we're not building the imported module, warn that we're going
- // to automatically turn this inclusion directive into a module import.
- // We only do this in Objective-C, where we have a module-import syntax.
- CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd),
- /*IsTokenRange=*/false);
- Diag(HashLoc, diag::warn_auto_module_import)
- << IncludeKind << PathString
- << FixItHint::CreateReplacement(ReplaceRange,
- "@import " + PathString.str().str() + ";");
- }
+ // We only do this in Objective-C, where we have a module-import syntax.
+ if (getLangOpts().ObjC2)
+ diagnoseAutoModuleImport(*this, HashLoc, IncludeTok, Path, CharEnd);
- // Load the module. Only make macros visible. We'll make the declarations
+ // Load the module to import its macros. We'll make the declarations
// visible when the parser gets here.
- Module::NameVisibilityKind Visibility = Module::MacrosVisible;
- ModuleLoadResult Imported
- = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
- /*IsIncludeDirective=*/true);
+ // FIXME: Pass SuggestedModule in here rather than converting it to a path
+ // and making the module loader convert it back again.
+ ModuleLoadResult Imported = TheModuleLoader.loadModule(
+ IncludeTok.getLocation(), Path, Module::Hidden,
+ /*IsIncludeDirective=*/true);
assert((Imported == nullptr || Imported == SuggestedModule.getModule()) &&
"the imported module is different than the suggested one");
- if (!Imported && hadModuleLoaderFatalFailure()) {
- // With a fatal failure in the module loader, we abort parsing.
- Token &Result = IncludeTok;
- if (CurLexer) {
- Result.startToken();
- CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
- CurLexer->cutOffLexing();
- } else {
- assert(CurPTHLexer && "#include but no current lexer set!");
- CurPTHLexer->getEOF(Result);
- }
- return;
- }
-
- // If this header isn't part of the module we're building, we're done.
- if (!BuildingImportedModule && Imported) {
- if (Callbacks) {
- Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
- FilenameRange, File,
- SearchPath, RelativePath, Imported);
- }
-
- if (IncludeKind != 3) {
- // Let the parser know that we hit a module import, and it should
- // make the module visible.
- // FIXME: Produce this as the current token directly, rather than
- // allocating a new token for it.
- EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include,
- Imported);
+ if (Imported)
+ ShouldEnter = false;
+ else if (Imported.isMissingExpected()) {
+ // We failed to find a submodule that we assumed would exist (because it
+ // was in the directory of an umbrella header, for instance), but no
+ // actual module exists for it (because the umbrella header is
+ // incomplete). Treat this as a textual inclusion.
+ SuggestedModule = ModuleMap::KnownHeader();
+ } else {
+ // We hit an error processing the import. Bail out.
+ if (hadModuleLoaderFatalFailure()) {
+ // With a fatal failure in the module loader, we abort parsing.
+ Token &Result = IncludeTok;
+ if (CurLexer) {
+ Result.startToken();
+ CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
+ CurLexer->cutOffLexing();
+ } else {
+ assert(CurPTHLexer && "#include but no current lexer set!");
+ CurPTHLexer->getEOF(Result);
+ }
}
return;
}
-
- // If we failed to find a submodule that we expected to find, we can
- // continue. Otherwise, there's an error in the included file, so we
- // don't want to include it.
- if (!BuildingImportedModule && !Imported.isMissingExpected()) {
- return;
- }
}
- if (Callbacks && SuggestedModule) {
- // We didn't notify the callback object that we've seen an inclusion
- // directive before. Now that we are parsing the include normally and not
- // turning it to a module import, notify the callback object.
- Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
- FilenameRange, File,
- SearchPath, RelativePath,
- /*ImportedModule=*/nullptr);
+ if (Callbacks) {
+ // Notify the callback object that we've seen an inclusion directive.
+ Callbacks->InclusionDirective(
+ HashLoc, IncludeTok,
+ LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
+ FilenameRange, File, SearchPath, RelativePath,
+ ShouldEnter ? nullptr : SuggestedModule.getModule());
}
+
+ if (!File)
+ return;
// The #included file will be considered to be a system header if either it is
// in a system include directory, or if the #includer is a system include
@@ -1752,11 +1743,29 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
std::max(HeaderInfo.getFileDirFlavor(File),
SourceMgr.getFileCharacteristic(FilenameTok.getLocation()));
+ // FIXME: If we have a suggested module, and we've already visited this file,
+ // don't bother entering it again. We know it has no further effect.
+
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
- if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) {
+ if (ShouldEnter &&
+ !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport,
+ SuggestedModule.getModule())) {
+ ShouldEnter = false;
if (Callbacks)
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
+ }
+
+ // If we don't need to enter the file, stop now.
+ if (!ShouldEnter) {
+ // If this is a module import, make it visible if needed.
+ if (auto *M = SuggestedModule.getModule()) {
+ makeModuleVisible(M, HashLoc);
+
+ if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
+ tok::pp___include_macros)
+ EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include, M);
+ }
return;
}
@@ -1769,26 +1778,24 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
assert(!FID.isInvalid() && "Expected valid file ID");
- // Determine if we're switching to building a new submodule, and which one.
- ModuleMap::KnownHeader BuildingModule;
- if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) {
- Module *RequestingModule = getModuleForLocation(FilenameLoc);
- BuildingModule =
- HeaderInfo.getModuleMap().findModuleForHeader(File, RequestingModule);
- }
-
// If all is good, enter the new file!
if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation()))
return;
- // If we're walking into another part of the same module, let the parser
- // know that any future declarations are within that other submodule.
- if (BuildingModule) {
+ // Determine if we're switching to building a new submodule, and which one.
+ if (auto *M = SuggestedModule.getModule()) {
assert(!CurSubmodule && "should not have marked this as a module yet");
- CurSubmodule = BuildingModule.getModule();
+ CurSubmodule = M;
- EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin,
- CurSubmodule);
+ // Let the macro handling code know that any future macros are within
+ // the new submodule.
+ EnterSubmodule(M, HashLoc);
+
+ // Let the parser know that any future declarations are within the new
+ // submodule.
+ // FIXME: There's no point doing this if we're handling a #__include_macros
+ // directive.
+ EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin, M);
}
}
@@ -2012,8 +2019,8 @@ static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI,
}
// #define inline
- if ((MacroName.is(tok::kw_extern) || MacroName.is(tok::kw_inline) ||
- MacroName.is(tok::kw_static) || MacroName.is(tok::kw_const)) &&
+ if (MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
+ tok::kw_const) &&
MI->getNumTokens() == 0) {
return true;
}
@@ -2290,9 +2297,9 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
// Check to see if this is the last token on the #undef line.
CheckEndOfDirective("undef");
- // Okay, we finally have a valid identifier to undef.
- MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
- const MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
+ // Okay, we have a valid identifier to undef.
+ auto *II = MacroNameTok.getIdentifierInfo();
+ auto MD = getMacroDefinition(II);
// If the callbacks want to know, tell them about the macro #undef.
// Note: no matter if the macro was defined or not.
@@ -2300,6 +2307,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
Callbacks->MacroUndefined(MacroNameTok, MD);
// If the macro is not defined, this is a noop undef, just return.
+ const MacroInfo *MI = MD.getMacroInfo();
if (!MI)
return;
@@ -2344,8 +2352,8 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
CheckEndOfDirective(isIfndef ? "ifndef" : "ifdef");
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
- MacroDirective *MD = getMacroDirective(MII);
- MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
+ auto MD = getMacroDefinition(MII);
+ MacroInfo *MI = MD.getMacroInfo();
if (CurPPLexer->getConditionalStackDepth() == 0) {
// If the start of a top-level #ifdef and if the macro is not defined,
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
index 9cf72cf..4451302 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
@@ -108,15 +108,13 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Otherwise, we got an identifier, is it defined to something?
IdentifierInfo *II = PeekTok.getIdentifierInfo();
- Result.Val = II->hasMacroDefinition();
- Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
+ MacroDefinition Macro = PP.getMacroDefinition(II);
+ Result.Val = !!Macro;
+ Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
- MacroDirective *Macro = nullptr;
// If there is a macro, mark it used.
- if (Result.Val != 0 && ValueLive) {
- Macro = PP.getMacroDirective(II);
- PP.markMacroAsUsed(Macro->getMacroInfo());
- }
+ if (Result.Val != 0 && ValueLive)
+ PP.markMacroAsUsed(Macro.getMacroInfo());
// Save macro token for callback.
Token macroToken(PeekTok);
@@ -144,11 +142,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Invoke the 'defined' callback.
if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
- MacroDirective *MD = Macro;
- // Pass the MacroInfo for the macro name even if the value is dead.
- if (!MD && Result.Val != 0)
- MD = PP.getMacroDirective(II);
- Callbacks->Defined(macroToken, MD,
+ Callbacks->Defined(macroToken, Macro,
SourceRange(beginLoc, PeekTok.getLocation()));
}
@@ -310,7 +304,9 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Set the value.
Val = Literal.getValue();
// Set the signedness. UTF-16 and UTF-32 are always unsigned
- if (!Literal.isUTF16() && !Literal.isUTF32())
+ if (Literal.isWide())
+ Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType()));
+ else if (!Literal.isUTF16() && !Literal.isUTF32())
Val.setIsUnsigned(!PP.getLangOpts().CharIsSigned);
if (Result.Val.getBitWidth() > Val.getBitWidth()) {
@@ -732,8 +728,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
/// may occur after a #if or #elif directive. If the expression is equivalent
/// to "!defined(X)" return X in IfNDefMacro.
-bool Preprocessor::
-EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
+bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true);
// Save the current state of 'DisableMacroExpansion' and reset it to false. If
// 'DisableMacroExpansion' is true, then we must be in a macro argument list
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
index fb5e2b0..c231e18 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -309,7 +309,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
if (const IdentifierInfo *DefinedMacro =
CurPPLexer->MIOpt.GetDefinedMacro()) {
- if (!ControllingMacro->hasMacroDefinition() &&
+ if (!isMacroDefined(ControllingMacro) &&
DefinedMacro != ControllingMacro &&
HeaderInfo.FirstTimeLexingFile(FE)) {
@@ -355,6 +355,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
PragmaARCCFCodeAuditedLoc = SourceLocation();
}
+ // Complain about reaching a true EOF within assume_nonnull.
+ // We don't want to complain about reaching the end of a macro
+ // instantiation or a _Pragma.
+ if (PragmaAssumeNonNullLoc.isValid() &&
+ !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) {
+ Diag(PragmaAssumeNonNullLoc, diag::err_pp_eof_in_assume_nonnull);
+
+ // Recover by leaving immediately.
+ PragmaAssumeNonNullLoc = SourceLocation();
+ }
+
// If this is a #include'd file, pop it off the include stack and continue
// lexing the #includer file.
if (!IncludeMacroStack.empty()) {
@@ -400,6 +411,9 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
Result.setAnnotationEndLoc(Result.getLocation());
Result.setAnnotationValue(CurSubmodule);
+
+ // We're done with this submodule.
+ LeaveSubmodule();
}
// We're done with the #included file.
@@ -471,7 +485,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (!getDiagnostics().isIgnored(diag::warn_uncovered_module_header,
StartLoc)) {
ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
- const DirectoryEntry *Dir = Mod->getUmbrellaDir();
+ const DirectoryEntry *Dir = Mod->getUmbrellaDir().Entry;
vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
std::error_code EC;
for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End;
@@ -605,3 +619,139 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
// preprocessor directive mode), so just return EOF as our token.
assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode");
}
+
+void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) {
+ if (!getLangOpts().ModulesLocalVisibility) {
+ // Just track that we entered this submodule.
+ BuildingSubmoduleStack.push_back(
+ BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState));
+ return;
+ }
+
+ // Resolve as much of the module definition as we can now, before we enter
+ // one of its headers.
+ // FIXME: Can we enable Complain here?
+ // FIXME: Can we do this when local visibility is disabled?
+ ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
+ ModMap.resolveExports(M, /*Complain=*/false);
+ ModMap.resolveUses(M, /*Complain=*/false);
+ ModMap.resolveConflicts(M, /*Complain=*/false);
+
+ // If this is the first time we've entered this module, set up its state.
+ auto R = Submodules.insert(std::make_pair(M, SubmoduleState()));
+ auto &State = R.first->second;
+ bool FirstTime = R.second;
+ if (FirstTime) {
+ // Determine the set of starting macros for this submodule; take these
+ // from the "null" module (the predefines buffer).
+ //
+ // FIXME: If we have local visibility but not modules enabled, the
+ // NullSubmoduleState is polluted by #defines in the top-level source
+ // file.
+ auto &StartingMacros = NullSubmoduleState.Macros;
+
+ // Restore to the starting state.
+ // FIXME: Do this lazily, when each macro name is first referenced.
+ for (auto &Macro : StartingMacros) {
+ // Skip uninteresting macros.
+ if (!Macro.second.getLatest() &&
+ Macro.second.getOverriddenMacros().empty())
+ continue;
+
+ MacroState MS(Macro.second.getLatest());
+ MS.setOverriddenMacros(*this, Macro.second.getOverriddenMacros());
+ State.Macros.insert(std::make_pair(Macro.first, std::move(MS)));
+ }
+ }
+
+ // Track that we entered this module.
+ BuildingSubmoduleStack.push_back(
+ BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState));
+
+ // Switch to this submodule as the current submodule.
+ CurSubmoduleState = &State;
+
+ // This module is visible to itself.
+ if (FirstTime)
+ makeModuleVisible(M, ImportLoc);
+}
+
+void Preprocessor::LeaveSubmodule() {
+ auto &Info = BuildingSubmoduleStack.back();
+
+ Module *LeavingMod = Info.M;
+ SourceLocation ImportLoc = Info.ImportLoc;
+
+ // Create ModuleMacros for any macros defined in this submodule.
+ for (auto &Macro : CurSubmoduleState->Macros) {
+ auto *II = const_cast<IdentifierInfo*>(Macro.first);
+
+ // Find the starting point for the MacroDirective chain in this submodule.
+ MacroDirective *OldMD = nullptr;
+ if (getLangOpts().ModulesLocalVisibility) {
+ // FIXME: It'd be better to start at the state from when we most recently
+ // entered this submodule, but it doesn't really matter.
+ auto &PredefMacros = NullSubmoduleState.Macros;
+ auto PredefMacroIt = PredefMacros.find(Macro.first);
+ if (PredefMacroIt == PredefMacros.end())
+ OldMD = nullptr;
+ else
+ OldMD = PredefMacroIt->second.getLatest();
+ }
+
+ // This module may have exported a new macro. If so, create a ModuleMacro
+ // representing that fact.
+ bool ExplicitlyPublic = false;
+ for (auto *MD = Macro.second.getLatest(); MD != OldMD;
+ MD = MD->getPrevious()) {
+ assert(MD && "broken macro directive chain");
+
+ // Stop on macros defined in other submodules we #included along the way.
+ // There's no point doing this if we're tracking local submodule
+ // visibility, since there can be no such directives in our list.
+ if (!getLangOpts().ModulesLocalVisibility) {
+ Module *Mod = getModuleContainingLocation(MD->getLocation());
+ if (Mod != LeavingMod)
+ break;
+ }
+
+ if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
+ // The latest visibility directive for a name in a submodule affects
+ // all the directives that come before it.
+ if (VisMD->isPublic())
+ ExplicitlyPublic = true;
+ else if (!ExplicitlyPublic)
+ // Private with no following public directive: not exported.
+ break;
+ } else {
+ MacroInfo *Def = nullptr;
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
+ Def = DefMD->getInfo();
+
+ // FIXME: Issue a warning if multiple headers for the same submodule
+ // define a macro, rather than silently ignoring all but the first.
+ bool IsNew;
+ // Don't bother creating a module macro if it would represent a #undef
+ // that doesn't override anything.
+ if (Def || !Macro.second.getOverriddenMacros().empty())
+ addModuleMacro(LeavingMod, II, Def,
+ Macro.second.getOverriddenMacros(), IsNew);
+ break;
+ }
+ }
+ }
+
+ // FIXME: Before we leave this submodule, we should parse all the other
+ // headers within it. Otherwise, we're left with an inconsistent state
+ // where we've made the module visible but don't yet have its complete
+ // contents.
+
+ // Put back the outer module's state, if we're tracking it.
+ if (getLangOpts().ModulesLocalVisibility)
+ CurSubmoduleState = Info.OuterSubmoduleState;
+
+ BuildingSubmoduleStack.pop_back();
+
+ // A nested #include makes the included submodule visible.
+ makeModuleVisible(LeavingMod, ImportLoc);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
index cd05d06..64ce8c9 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
@@ -34,44 +34,234 @@
using namespace clang;
MacroDirective *
-Preprocessor::getMacroDirectiveHistory(const IdentifierInfo *II) const {
- assert(II->hadMacroDefinition() && "Identifier has not been not a macro!");
-
- macro_iterator Pos = Macros.find(II);
- assert(Pos != Macros.end() && "Identifier macro info is missing!");
- return Pos->second;
+Preprocessor::getLocalMacroDirectiveHistory(const IdentifierInfo *II) const {
+ if (!II->hadMacroDefinition())
+ return nullptr;
+ auto Pos = CurSubmoduleState->Macros.find(II);
+ return Pos == CurSubmoduleState->Macros.end() ? nullptr
+ : Pos->second.getLatest();
}
void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){
assert(MD && "MacroDirective should be non-zero!");
assert(!MD->getPrevious() && "Already attached to a MacroDirective history.");
- MacroDirective *&StoredMD = Macros[II];
- MD->setPrevious(StoredMD);
- StoredMD = MD;
- // Setup the identifier as having associated macro history.
+ MacroState &StoredMD = CurSubmoduleState->Macros[II];
+ auto *OldMD = StoredMD.getLatest();
+ MD->setPrevious(OldMD);
+ StoredMD.setLatest(MD);
+ StoredMD.overrideActiveModuleMacros(*this, II);
+
+ // Set up the identifier as having associated macro history.
II->setHasMacroDefinition(true);
- if (!MD->isDefined())
+ if (!MD->isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end())
II->setHasMacroDefinition(false);
- bool isImportedMacro = isa<DefMacroDirective>(MD) &&
- cast<DefMacroDirective>(MD)->isImported();
- if (II->isFromAST() && !isImportedMacro)
+ if (II->isFromAST())
II->setChangedSinceDeserialization();
}
void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II,
MacroDirective *MD) {
assert(II && MD);
- MacroDirective *&StoredMD = Macros[II];
- assert(!StoredMD &&
+ MacroState &StoredMD = CurSubmoduleState->Macros[II];
+ assert(!StoredMD.getLatest() &&
"the macro history was modified before initializing it from a pch");
StoredMD = MD;
// Setup the identifier as having associated macro history.
II->setHasMacroDefinition(true);
- if (!MD->isDefined())
+ if (!MD->isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end())
II->setHasMacroDefinition(false);
}
+ModuleMacro *Preprocessor::addModuleMacro(Module *Mod, IdentifierInfo *II,
+ MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides,
+ bool &New) {
+ llvm::FoldingSetNodeID ID;
+ ModuleMacro::Profile(ID, Mod, II);
+
+ void *InsertPos;
+ if (auto *MM = ModuleMacros.FindNodeOrInsertPos(ID, InsertPos)) {
+ New = false;
+ return MM;
+ }
+
+ auto *MM = ModuleMacro::create(*this, Mod, II, Macro, Overrides);
+ ModuleMacros.InsertNode(MM, InsertPos);
+
+ // Each overridden macro is now overridden by one more macro.
+ bool HidAny = false;
+ for (auto *O : Overrides) {
+ HidAny |= (O->NumOverriddenBy == 0);
+ ++O->NumOverriddenBy;
+ }
+
+ // If we were the first overrider for any macro, it's no longer a leaf.
+ auto &LeafMacros = LeafModuleMacros[II];
+ if (HidAny) {
+ LeafMacros.erase(std::remove_if(LeafMacros.begin(), LeafMacros.end(),
+ [](ModuleMacro *MM) {
+ return MM->NumOverriddenBy != 0;
+ }),
+ LeafMacros.end());
+ }
+
+ // The new macro is always a leaf macro.
+ LeafMacros.push_back(MM);
+ // The identifier now has defined macros (that may or may not be visible).
+ II->setHasMacroDefinition(true);
+
+ New = true;
+ return MM;
+}
+
+ModuleMacro *Preprocessor::getModuleMacro(Module *Mod, IdentifierInfo *II) {
+ llvm::FoldingSetNodeID ID;
+ ModuleMacro::Profile(ID, Mod, II);
+
+ void *InsertPos;
+ return ModuleMacros.FindNodeOrInsertPos(ID, InsertPos);
+}
+
+void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II,
+ ModuleMacroInfo &Info) {
+ assert(Info.ActiveModuleMacrosGeneration !=
+ CurSubmoduleState->VisibleModules.getGeneration() &&
+ "don't need to update this macro name info");
+ Info.ActiveModuleMacrosGeneration =
+ CurSubmoduleState->VisibleModules.getGeneration();
+
+ auto Leaf = LeafModuleMacros.find(II);
+ if (Leaf == LeafModuleMacros.end()) {
+ // No imported macros at all: nothing to do.
+ return;
+ }
+
+ Info.ActiveModuleMacros.clear();
+
+ // Every macro that's locally overridden is overridden by a visible macro.
+ llvm::DenseMap<ModuleMacro *, int> NumHiddenOverrides;
+ for (auto *O : Info.OverriddenMacros)
+ NumHiddenOverrides[O] = -1;
+
+ // Collect all macros that are not overridden by a visible macro.
+ llvm::SmallVector<ModuleMacro *, 16> Worklist(Leaf->second.begin(),
+ Leaf->second.end());
+ while (!Worklist.empty()) {
+ auto *MM = Worklist.pop_back_val();
+ if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) {
+ // We only care about collecting definitions; undefinitions only act
+ // to override other definitions.
+ if (MM->getMacroInfo())
+ Info.ActiveModuleMacros.push_back(MM);
+ } else {
+ for (auto *O : MM->overrides())
+ if ((unsigned)++NumHiddenOverrides[O] == O->getNumOverridingMacros())
+ Worklist.push_back(O);
+ }
+ }
+ // Our reverse postorder walk found the macros in reverse order.
+ std::reverse(Info.ActiveModuleMacros.begin(), Info.ActiveModuleMacros.end());
+
+ // Determine whether the macro name is ambiguous.
+ MacroInfo *MI = nullptr;
+ bool IsSystemMacro = true;
+ bool IsAmbiguous = false;
+ if (auto *MD = Info.MD) {
+ while (MD && isa<VisibilityMacroDirective>(MD))
+ MD = MD->getPrevious();
+ if (auto *DMD = dyn_cast_or_null<DefMacroDirective>(MD)) {
+ MI = DMD->getInfo();
+ IsSystemMacro &= SourceMgr.isInSystemHeader(DMD->getLocation());
+ }
+ }
+ for (auto *Active : Info.ActiveModuleMacros) {
+ auto *NewMI = Active->getMacroInfo();
+
+ // Before marking the macro as ambiguous, check if this is a case where
+ // both macros are in system headers. If so, we trust that the system
+ // did not get it wrong. This also handles cases where Clang's own
+ // headers have a different spelling of certain system macros:
+ // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
+ // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
+ //
+ // FIXME: Remove the defined-in-system-headers check. clang's limits.h
+ // overrides the system limits.h's macros, so there's no conflict here.
+ if (MI && NewMI != MI &&
+ !MI->isIdenticalTo(*NewMI, *this, /*Syntactically=*/true))
+ IsAmbiguous = true;
+ IsSystemMacro &= Active->getOwningModule()->IsSystem ||
+ SourceMgr.isInSystemHeader(NewMI->getDefinitionLoc());
+ MI = NewMI;
+ }
+ Info.IsAmbiguous = IsAmbiguous && !IsSystemMacro;
+}
+
+void Preprocessor::dumpMacroInfo(const IdentifierInfo *II) {
+ ArrayRef<ModuleMacro*> Leaf;
+ auto LeafIt = LeafModuleMacros.find(II);
+ if (LeafIt != LeafModuleMacros.end())
+ Leaf = LeafIt->second;
+ const MacroState *State = nullptr;
+ auto Pos = CurSubmoduleState->Macros.find(II);
+ if (Pos != CurSubmoduleState->Macros.end())
+ State = &Pos->second;
+
+ llvm::errs() << "MacroState " << State << " " << II->getNameStart();
+ if (State && State->isAmbiguous(*this, II))
+ llvm::errs() << " ambiguous";
+ if (State && !State->getOverriddenMacros().empty()) {
+ llvm::errs() << " overrides";
+ for (auto *O : State->getOverriddenMacros())
+ llvm::errs() << " " << O->getOwningModule()->getFullModuleName();
+ }
+ llvm::errs() << "\n";
+
+ // Dump local macro directives.
+ for (auto *MD = State ? State->getLatest() : nullptr; MD;
+ MD = MD->getPrevious()) {
+ llvm::errs() << " ";
+ MD->dump();
+ }
+
+ // Dump module macros.
+ llvm::DenseSet<ModuleMacro*> Active;
+ for (auto *MM : State ? State->getActiveModuleMacros(*this, II) : None)
+ Active.insert(MM);
+ llvm::DenseSet<ModuleMacro*> Visited;
+ llvm::SmallVector<ModuleMacro *, 16> Worklist(Leaf.begin(), Leaf.end());
+ while (!Worklist.empty()) {
+ auto *MM = Worklist.pop_back_val();
+ llvm::errs() << " ModuleMacro " << MM << " "
+ << MM->getOwningModule()->getFullModuleName();
+ if (!MM->getMacroInfo())
+ llvm::errs() << " undef";
+
+ if (Active.count(MM))
+ llvm::errs() << " active";
+ else if (!CurSubmoduleState->VisibleModules.isVisible(
+ MM->getOwningModule()))
+ llvm::errs() << " hidden";
+ else if (MM->getMacroInfo())
+ llvm::errs() << " overridden";
+
+ if (!MM->overrides().empty()) {
+ llvm::errs() << " overrides";
+ for (auto *O : MM->overrides()) {
+ llvm::errs() << " " << O->getOwningModule()->getFullModuleName();
+ if (Visited.insert(O).second)
+ Worklist.push_back(O);
+ }
+ }
+ llvm::errs() << "\n";
+ if (auto *MI = MM->getMacroInfo()) {
+ llvm::errs() << " ";
+ MI->dump();
+ llvm::errs() << "\n";
+ }
+ }
+}
+
/// RegisterBuiltinMacro - Register the specified identifier in the identifier
/// table and mark it as a builtin macro to be expanded.
static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
@@ -97,7 +287,11 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
// C++ Standing Document Extensions.
- Ident__has_cpp_attribute = RegisterBuiltinMacro(*this, "__has_cpp_attribute");
+ if (LangOpts.CPlusPlus)
+ Ident__has_cpp_attribute =
+ RegisterBuiltinMacro(*this, "__has_cpp_attribute");
+ else
+ Ident__has_cpp_attribute = nullptr;
// GCC Extensions.
Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__");
@@ -156,10 +350,11 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
// If the identifier is a macro, and if that macro is enabled, it may be
// expanded so it's not a trivial expansion.
- if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled() &&
- // Fast expanding "#define X X" is ok, because X would be disabled.
- II != MacroIdent)
- return false;
+ if (auto *ExpansionMI = PP.getMacroInfo(II))
+ if (ExpansionMI->isEnabled() &&
+ // Fast expanding "#define X X" is ok, because X would be disabled.
+ II != MacroIdent)
+ return false;
// If this is an object-like macro invocation, it is safe to trivially expand
// it.
@@ -167,12 +362,8 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
// If this is a function-like macro invocation, it's safe to trivially expand
// as long as the identifier is not a macro argument.
- for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
- I != E; ++I)
- if (*I == II)
- return false; // Identifier is a macro argument.
+ return std::find(MI->arg_begin(), MI->arg_end(), II) == MI->arg_end();
- return true;
}
@@ -222,10 +413,8 @@ bool Preprocessor::isNextPPTokenLParen() {
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to be
/// expanded as a macro, handle it and return the next token as 'Identifier'.
bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
- MacroDirective *MD) {
- MacroDirective::DefInfo Def = MD->getDefinition();
- assert(Def.isValid());
- MacroInfo *MI = Def.getMacroInfo();
+ const MacroDefinition &M) {
+ MacroInfo *MI = M.getMacroInfo();
// If this is a macro expansion in the "#if !defined(x)" line for the file,
// then the macro could expand to different things in other contexts, we need
@@ -234,9 +423,9 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
if (MI->isBuiltinMacro()) {
- if (Callbacks) Callbacks->MacroExpands(Identifier, MD,
- Identifier.getLocation(),
- /*Args=*/nullptr);
+ if (Callbacks)
+ Callbacks->MacroExpands(Identifier, M, Identifier.getLocation(),
+ /*Args=*/nullptr);
ExpandBuiltinMacro(Identifier);
return true;
}
@@ -283,9 +472,9 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
// MacroExpands callbacks still happen in source order, queue this
// callback to have it happen after the function macro callback.
DelayedMacroExpandsCallbacks.push_back(
- MacroExpandsInfo(Identifier, MD, ExpansionRange));
+ MacroExpandsInfo(Identifier, M, ExpansionRange));
} else {
- Callbacks->MacroExpands(Identifier, MD, ExpansionRange, Args);
+ Callbacks->MacroExpands(Identifier, M, ExpansionRange, Args);
if (!DelayedMacroExpandsCallbacks.empty()) {
for (unsigned i=0, e = DelayedMacroExpandsCallbacks.size(); i!=e; ++i) {
MacroExpandsInfo &Info = DelayedMacroExpandsCallbacks[i];
@@ -299,20 +488,16 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
}
// If the macro definition is ambiguous, complain.
- if (Def.getDirective()->isAmbiguous()) {
+ if (M.isAmbiguous()) {
Diag(Identifier, diag::warn_pp_ambiguous_macro)
<< Identifier.getIdentifierInfo();
Diag(MI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_chosen)
<< Identifier.getIdentifierInfo();
- for (MacroDirective::DefInfo PrevDef = Def.getPreviousDefinition();
- PrevDef && !PrevDef.isUndefined();
- PrevDef = PrevDef.getPreviousDefinition()) {
- Diag(PrevDef.getMacroInfo()->getDefinitionLoc(),
- diag::note_pp_ambiguous_macro_other)
- << Identifier.getIdentifierInfo();
- if (!PrevDef.getDirective()->isAmbiguous())
- break;
- }
+ M.forAllDefinitions([&](const MacroInfo *OtherMI) {
+ if (OtherMI != MI)
+ Diag(OtherMI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_other)
+ << Identifier.getIdentifierInfo();
+ });
}
// If we started lexing a macro, enter the macro expansion body.
@@ -541,10 +726,10 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
unsigned NumActuals = 0;
while (Tok.isNot(tok::r_paren)) {
- if (ContainsCodeCompletionTok && (Tok.is(tok::eof) || Tok.is(tok::eod)))
+ if (ContainsCodeCompletionTok && Tok.isOneOf(tok::eof, tok::eod))
break;
- assert((Tok.is(tok::l_paren) || Tok.is(tok::comma)) &&
+ assert(Tok.isOneOf(tok::l_paren, tok::comma) &&
"only expect argument separators here");
unsigned ArgTokenStart = ArgTokens.size();
@@ -559,7 +744,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
// an argument value in a macro could expand to ',' or '(' or ')'.
LexUnexpandedToken(Tok);
- if (Tok.is(tok::eof) || Tok.is(tok::eod)) { // "#if f(<eof>" & "#if f(\n"
+ if (Tok.isOneOf(tok::eof, tok::eod)) { // "#if f(<eof>" & "#if f(\n"
if (!ContainsCodeCompletionTok) {
Diag(MacroName, diag::err_unterm_macro_invoc);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
@@ -598,7 +783,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
// If this is a comment token in the argument list and we're just in
// -C mode (not -CC mode), discard the comment.
continue;
- } else if (Tok.getIdentifierInfo() != nullptr) {
+ } else if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != nullptr) {
// Reading macro arguments can cause macros that we are currently
// expanding from to be popped off the expansion stack. Doing so causes
// them to be reenabled for expansion. Here we record whether any
@@ -864,12 +1049,17 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
Feature = Feature.substr(2, Feature.size() - 4);
return llvm::StringSwitch<bool>(Feature)
- .Case("address_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Address))
+ .Case("address_sanitizer",
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
+ .Case("assume_nonnull", true)
.Case("attribute_analyzer_noreturn", true)
.Case("attribute_availability", true)
.Case("attribute_availability_with_message", true)
+ .Case("attribute_availability_app_extension", true)
.Case("attribute_cf_returns_not_retained", true)
.Case("attribute_cf_returns_retained", true)
+ .Case("attribute_cf_returns_on_parameters", true)
.Case("attribute_deprecated_with_message", true)
.Case("attribute_ext_vector_type", true)
.Case("attribute_ns_returns_not_retained", true)
@@ -887,6 +1077,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_exceptions", LangOpts.CXXExceptions)
.Case("cxx_rtti", LangOpts.RTTI)
.Case("enumerator_attributes", true)
+ .Case("nullability", true)
.Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
.Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread))
.Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
@@ -897,6 +1088,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("objc_default_synthesize_properties", LangOpts.ObjC2)
.Case("objc_fixed_enum", LangOpts.ObjC2)
.Case("objc_instancetype", LangOpts.ObjC2)
+ .Case("objc_kindof", LangOpts.ObjC2)
.Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules)
.Case("objc_nonfragile_abi", LangOpts.ObjCRuntime.isNonFragile())
.Case("objc_property_explicit_atomic",
@@ -911,8 +1103,12 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("objc_array_literals", LangOpts.ObjC2)
.Case("objc_dictionary_literals", LangOpts.ObjC2)
.Case("objc_boxed_expressions", LangOpts.ObjC2)
+ .Case("objc_boxed_nsvalue_expressions", LangOpts.ObjC2)
.Case("arc_cf_code_audited", true)
- .Case("objc_bridge_id", LangOpts.ObjC2)
+ .Case("objc_bridge_id", true)
+ .Case("objc_bridge_id_on_typedefs", true)
+ .Case("objc_generics", LangOpts.ObjC2)
+ .Case("objc_generics_variance", LangOpts.ObjC2)
// C11 features
.Case("c_alignas", LangOpts.C11)
.Case("c_alignof", LangOpts.C11)
@@ -1003,6 +1199,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("is_trivially_copyable", LangOpts.CPlusPlus)
.Case("is_union", LangOpts.CPlusPlus)
.Case("modules", LangOpts.Modules)
+ .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
.Case("tls", PP.getTargetInfo().isTLSSupported())
.Case("underlying_type", LangOpts.CPlusPlus)
.Default(false);
@@ -1050,6 +1247,7 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_range_for", LangOpts.CPlusPlus)
.Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
.Case("cxx_rvalue_references", LangOpts.CPlusPlus)
+ .Case("cxx_variadic_templates", LangOpts.CPlusPlus)
// C++1y features supported by other languages as extensions.
.Case("cxx_binary_literals", true)
.Case("cxx_init_captures", LangOpts.CPlusPlus11)
@@ -1071,6 +1269,9 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
// These expressions are only allowed within a preprocessor directive.
if (!PP.isParsingIfOrElifDirective()) {
PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName();
+ // Return a valid identifier token.
+ assert(Tok.is(tok::identifier));
+ Tok.setIdentifierInfo(II);
return false;
}
@@ -1129,7 +1330,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
Tok.setKind(tok::eod);
return false; // Found <eod> but no ">"? Diagnostic already emitted.
}
- Filename = FilenameBuffer.str();
+ Filename = FilenameBuffer;
break;
default:
PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);
@@ -1179,7 +1380,7 @@ static bool EvaluateHasIncludeNext(Token &Tok,
// __has_include_next is like __has_include, except that we start
// searching after the current found directory. If we can't do this,
// issue a diagnostic.
- // FIXME: Factor out duplication wiht
+ // FIXME: Factor out duplication with
// Preprocessor::HandleIncludeNextDirective.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
const FileEntry *LookupFromFile = nullptr;
@@ -1312,7 +1513,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
if (PLoc.isValid()) {
FN += PLoc.getFilename();
Lexer::Stringify(FN);
- OS << '"' << FN.str() << '"';
+ OS << '"' << FN << '"';
}
Tok.setKind(tok::string_literal);
} else if (II == Ident__DATE__) {
@@ -1459,9 +1660,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Value = EvaluateHasInclude(Tok, II, *this);
else
Value = EvaluateHasIncludeNext(Tok, II, *this);
+
+ if (Tok.isNot(tok::r_paren))
+ return;
OS << (int)Value;
- if (Tok.is(tok::r_paren))
- Tok.setKind(tok::numeric_constant);
+ Tok.setKind(tok::numeric_constant);
} else if (II == Ident__has_warning) {
// The argument should be a parenthesized string literal.
// The argument to these builtins should be a parenthesized identifier.
@@ -1553,7 +1756,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Diag(Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)
<< Tok.getKind();
// Don't walk past anything that's not a real token.
- if (Tok.is(tok::eof) || Tok.is(tok::eod) || Tok.isAnnotation())
+ if (Tok.isOneOf(tok::eof, tok::eod) || Tok.isAnnotation())
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
index af7a153..5f63d35 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
@@ -431,8 +431,7 @@ static void InvalidPTH(DiagnosticsEngine &Diags, const char *Msg) {
Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) << Msg;
}
-PTHManager *PTHManager::Create(const std::string &file,
- DiagnosticsEngine &Diags) {
+PTHManager *PTHManager::Create(StringRef file, DiagnosticsEngine &Diags) {
// Memory map the PTH file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
llvm::MemoryBuffer::getFile(file);
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index 8ed8328..5eb6655 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -22,6 +22,7 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -400,7 +401,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
if (II->isPoisoned()) continue;
// If this is a macro identifier, emit a warning.
- if (II->hasMacroDefinition())
+ if (isMacroDefined(II))
Diag(Tok, diag::pp_poisoning_existing_macro);
// Finally, poison it!
@@ -590,8 +591,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
PragmaPushMacroInfo.find(IdentInfo);
if (iter != PragmaPushMacroInfo.end()) {
// Forget the MacroInfo currently associated with IdentInfo.
- if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) {
- MacroInfo *MI = CurrentMD->getMacroInfo();
+ if (MacroInfo *MI = getMacroInfo(IdentInfo)) {
if (MI->isWarnIfUnused())
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc));
@@ -600,11 +600,9 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
// Get the MacroInfo we want to reinstall.
MacroInfo *MacroToReInstall = iter->second.back();
- if (MacroToReInstall) {
+ if (MacroToReInstall)
// Reinstall the previously pushed macro.
- appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc,
- /*isImported=*/false, /*Overrides*/None);
- }
+ appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc);
// Pop PragmaPushMacroInfo stack.
iter->second.pop_back();
@@ -648,7 +646,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
SourceLocation End;
if (ConcatenateIncludeName(FileNameBuffer, End))
return; // Diagnostic already emitted
- SourceFileName = FileNameBuffer.str();
+ SourceFileName = FileNameBuffer;
} else {
Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
return;
@@ -679,7 +677,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
SourceLocation End;
if (ConcatenateIncludeName(FileNameBuffer, End))
return; // Diagnostic already emitted
- ReplaceFileName = FileNameBuffer.str();
+ ReplaceFileName = FileNameBuffer;
} else {
Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
return;
@@ -870,12 +868,22 @@ struct PragmaDebugHandler : public PragmaHandler {
LLVM_BUILTIN_TRAP;
} else if (II->isStr("parser_crash")) {
Token Crasher;
+ Crasher.startToken();
Crasher.setKind(tok::annot_pragma_parser_crash);
+ Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
PP.EnterToken(Crasher);
} else if (II->isStr("llvm_fatal_error")) {
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
} else if (II->isStr("llvm_unreachable")) {
llvm_unreachable("#pragma clang __debug llvm_unreachable");
+ } else if (II->isStr("macro")) {
+ Token MacroName;
+ PP.LexUnexpandedToken(MacroName);
+ auto *MacroII = MacroName.getIdentifierInfo();
+ if (MacroII)
+ PP.dumpMacroInfo(MacroII);
+ else
+ PP.Diag(MacroName, diag::warn_pragma_diagnostic_invalid);
} else if (II->isStr("overflow_stack")) {
DebugOverflowStack();
} else if (II->isStr("handle_crash")) {
@@ -1029,12 +1037,8 @@ struct PragmaWarningHandler : public PragmaHandler {
PP.Lex(Tok);
IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II) {
- PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
- return;
- }
- if (II->isStr("push")) {
+ if (II && II->isStr("push")) {
// #pragma warning( push[ ,n ] )
int Level = -1;
PP.Lex(Tok);
@@ -1051,7 +1055,7 @@ struct PragmaWarningHandler : public PragmaHandler {
}
if (Callbacks)
Callbacks->PragmaWarningPush(DiagLoc, Level);
- } else if (II->isStr("pop")) {
+ } else if (II && II->isStr("pop")) {
// #pragma warning( pop )
PP.Lex(Tok);
if (Callbacks)
@@ -1061,23 +1065,40 @@ struct PragmaWarningHandler : public PragmaHandler {
// [; warning-specifier : warning-number-list...] )
while (true) {
II = Tok.getIdentifierInfo();
- if (!II) {
+ if (!II && !Tok.is(tok::numeric_constant)) {
PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
return;
}
// Figure out which warning specifier this is.
- StringRef Specifier = II->getName();
- bool SpecifierValid =
- llvm::StringSwitch<bool>(Specifier)
- .Cases("1", "2", "3", "4", true)
- .Cases("default", "disable", "error", "once", "suppress", true)
- .Default(false);
+ bool SpecifierValid;
+ StringRef Specifier;
+ llvm::SmallString<1> SpecifierBuf;
+ if (II) {
+ Specifier = II->getName();
+ SpecifierValid = llvm::StringSwitch<bool>(Specifier)
+ .Cases("default", "disable", "error", "once",
+ "suppress", true)
+ .Default(false);
+ // If we read a correct specifier, snatch next token (that should be
+ // ":", checked later).
+ if (SpecifierValid)
+ PP.Lex(Tok);
+ } else {
+ // Token is a numeric constant. It should be either 1, 2, 3 or 4.
+ uint64_t Value;
+ Specifier = PP.getSpelling(Tok, SpecifierBuf);
+ if (PP.parseSimpleIntegerLiteral(Tok, Value)) {
+ SpecifierValid = (Value >= 1) && (Value <= 4);
+ } else
+ SpecifierValid = false;
+ // Next token already snatched by parseSimpleIntegerLiteral.
+ }
+
if (!SpecifierValid) {
PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
return;
}
- PP.Lex(Tok);
if (Tok.isNot(tok::colon)) {
PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":";
return;
@@ -1321,6 +1342,60 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
}
};
+/// PragmaAssumeNonNullHandler -
+/// \#pragma clang assume_nonnull begin/end
+struct PragmaAssumeNonNullHandler : public PragmaHandler {
+ PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &NameTok) override {
+ SourceLocation Loc = NameTok.getLocation();
+ bool IsBegin;
+
+ Token Tok;
+
+ // Lex the 'begin' or 'end'.
+ PP.LexUnexpandedToken(Tok);
+ const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo();
+ if (BeginEnd && BeginEnd->isStr("begin")) {
+ IsBegin = true;
+ } else if (BeginEnd && BeginEnd->isStr("end")) {
+ IsBegin = false;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_pp_assume_nonnull_syntax);
+ return;
+ }
+
+ // Verify that this is followed by EOD.
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::eod))
+ PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
+
+ // The start location of the active audit.
+ SourceLocation BeginLoc = PP.getPragmaAssumeNonNullLoc();
+
+ // The start location we want after processing this.
+ SourceLocation NewLoc;
+
+ if (IsBegin) {
+ // Complain about attempts to re-enter an audit.
+ if (BeginLoc.isValid()) {
+ PP.Diag(Loc, diag::err_pp_double_begin_of_assume_nonnull);
+ PP.Diag(BeginLoc, diag::note_pragma_entered_here);
+ }
+ NewLoc = Loc;
+ } else {
+ // Complain about attempts to leave an audit that doesn't exist.
+ if (!BeginLoc.isValid()) {
+ PP.Diag(Loc, diag::err_pp_unmatched_end_of_assume_nonnull);
+ return;
+ }
+ NewLoc = SourceLocation();
+ }
+
+ PP.setPragmaAssumeNonNullLoc(NewLoc);
+ }
+};
+
/// \brief Handle "\#pragma region [...]"
///
/// The syntax is
@@ -1372,6 +1447,7 @@ void Preprocessor::RegisterBuiltinPragmas() {
AddPragmaHandler("clang", new PragmaDependencyHandler());
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
+ AddPragmaHandler("clang", new PragmaAssumeNonNullHandler());
AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
index 41bb581..a423041 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
@@ -45,22 +45,23 @@ PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
/// that source range \p Range encompasses.
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+llvm::iterator_range<PreprocessingRecord::iterator>
PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
if (Range.isInvalid())
- return std::make_pair(iterator(), iterator());
+ return llvm::make_range(iterator(), iterator());
if (CachedRangeQuery.Range == Range) {
- return std::make_pair(iterator(this, CachedRangeQuery.Result.first),
- iterator(this, CachedRangeQuery.Result.second));
+ return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
+ iterator(this, CachedRangeQuery.Result.second));
}
std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
CachedRangeQuery.Range = Range;
CachedRangeQuery.Result = Res;
-
- return std::make_pair(iterator(this, Res.first), iterator(this, Res.second));
+
+ return llvm::make_range(iterator(this, Res.first),
+ iterator(this, Res.second));
}
static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
@@ -72,11 +73,8 @@ static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
SourceLocation Loc = PPE->getSourceRange().getBegin();
if (Loc.isInvalid())
return false;
-
- if (SM.isInFileID(SM.getFileLoc(Loc), FID))
- return true;
- else
- return false;
+
+ return SM.isInFileID(SM.getFileLoc(Loc), FID);
}
/// \brief Returns true if the preprocessed entity that \arg PPEI iterator
@@ -90,7 +88,7 @@ bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
if (FID.isInvalid())
return false;
- int Pos = PPEI.Position;
+ int Pos = std::distance(iterator(this, 0), PPEI);
if (Pos < 0) {
if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
assert(0 && "Out-of bounds loaded preprocessed entity");
@@ -248,10 +246,11 @@ PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
assert(Entity);
SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
- if (isa<MacroDefinition>(Entity)) {
+ if (isa<MacroDefinitionRecord>(Entity)) {
assert((PreprocessedEntities.empty() ||
- !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
- PreprocessedEntities.back()->getSourceRange().getBegin())) &&
+ !SourceMgr.isBeforeInTranslationUnit(
+ BeginLoc,
+ PreprocessedEntities.back()->getSourceRange().getBegin())) &&
"a macro definition was encountered out-of-order");
PreprocessedEntities.push_back(Entity);
return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
@@ -320,7 +319,7 @@ unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
}
void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
- MacroDefinition *Def) {
+ MacroDefinitionRecord *Def) {
MacroDefinitions[Macro] = Def;
}
@@ -357,9 +356,10 @@ PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
return Entity;
}
-MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
- llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
- = MacroDefinitions.find(MI);
+MacroDefinitionRecord *
+PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
+ llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
+ MacroDefinitions.find(MI);
if (Pos == MacroDefinitions.end())
return nullptr;
@@ -374,35 +374,34 @@ void PreprocessingRecord::addMacroExpansion(const Token &Id,
return;
if (MI->isBuiltinMacro())
- addPreprocessedEntity(
- new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
- else if (MacroDefinition *Def = findMacroDefinition(MI))
- addPreprocessedEntity(
- new (*this) MacroExpansion(Def, Range));
+ addPreprocessedEntity(new (*this)
+ MacroExpansion(Id.getIdentifierInfo(), Range));
+ else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
+ addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
}
void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD) {
+ const MacroDefinition &MD) {
// This is not actually a macro expansion but record it as a macro reference.
if (MD)
- addMacroExpansion(MacroNameTok, MD->getMacroInfo(),
+ addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
MacroNameTok.getLocation());
}
void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD) {
+ const MacroDefinition &MD) {
// This is not actually a macro expansion but record it as a macro reference.
if (MD)
- addMacroExpansion(MacroNameTok, MD->getMacroInfo(),
+ addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
MacroNameTok.getLocation());
}
void PreprocessingRecord::Defined(const Token &MacroNameTok,
- const MacroDirective *MD,
+ const MacroDefinition &MD,
SourceRange Range) {
// This is not actually a macro expansion but record it as a macro reference.
if (MD)
- addMacroExpansion(MacroNameTok, MD->getMacroInfo(),
+ addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
MacroNameTok.getLocation());
}
@@ -410,27 +409,26 @@ void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
SkippedRanges.push_back(Range);
}
-void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD,
+void PreprocessingRecord::MacroExpands(const Token &Id,
+ const MacroDefinition &MD,
SourceRange Range,
const MacroArgs *Args) {
- addMacroExpansion(Id, MD->getMacroInfo(), Range);
+ addMacroExpansion(Id, MD.getMacroInfo(), Range);
}
void PreprocessingRecord::MacroDefined(const Token &Id,
const MacroDirective *MD) {
const MacroInfo *MI = MD->getMacroInfo();
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
- MacroDefinition *Def
- = new (*this) MacroDefinition(Id.getIdentifierInfo(), R);
+ MacroDefinitionRecord *Def =
+ new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
addPreprocessedEntity(Def);
MacroDefinitions[MI] = Def;
}
void PreprocessingRecord::MacroUndefined(const Token &Id,
- const MacroDirective *MD) {
- // Note: MI may be null (when #undef'ining an undefined macro).
- if (MD)
- MacroDefinitions.erase(MD->getMacroInfo());
+ const MacroDefinition &MD) {
+ MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
}
void PreprocessingRecord::InclusionDirective(
diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
index b2a6d93..e2db638 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
@@ -73,7 +73,8 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
ModuleImportExpectsIdentifier(false), CodeCompletionReached(0),
MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr),
- Callbacks(nullptr), MacroArgCache(nullptr), Record(nullptr),
+ Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState),
+ MacroArgCache(nullptr), Record(nullptr),
MIChainHead(nullptr), DeserialMIChainHead(nullptr) {
OwnsHeaderSearch = OwnsHeaders;
@@ -266,7 +267,9 @@ void Preprocessor::PrintStats() {
llvm::errs() << "\n Macro Expanded Tokens: "
<< llvm::capacity_in_bytes(MacroExpandedTokens);
llvm::errs() << "\n Predefines Buffer: " << Predefines.capacity();
- llvm::errs() << "\n Macros: " << llvm::capacity_in_bytes(Macros);
+ // FIXME: List information for all submodules.
+ llvm::errs() << "\n Macros: "
+ << llvm::capacity_in_bytes(CurSubmoduleState->Macros);
llvm::errs() << "\n #pragma push_macro Info: "
<< llvm::capacity_in_bytes(PragmaPushMacroInfo);
llvm::errs() << "\n Poison Reasons: "
@@ -283,14 +286,20 @@ Preprocessor::macro_begin(bool IncludeExternalMacros) const {
ExternalSource->ReadDefinedMacros();
}
- return Macros.begin();
+ // Make sure we cover all macros in visible modules.
+ for (const ModuleMacro &Macro : ModuleMacros)
+ CurSubmoduleState->Macros.insert(std::make_pair(Macro.II, MacroState()));
+
+ return CurSubmoduleState->Macros.begin();
}
size_t Preprocessor::getTotalMemory() const {
return BP.getTotalMemory()
+ llvm::capacity_in_bytes(MacroExpandedTokens)
+ Predefines.capacity() /* Predefines buffer. */
- + llvm::capacity_in_bytes(Macros)
+ // FIXME: Include sizes from all submodules, and include MacroInfo sizes,
+ // and ModuleMacros.
+ + llvm::capacity_in_bytes(CurSubmoduleState->Macros)
+ llvm::capacity_in_bytes(PragmaPushMacroInfo)
+ llvm::capacity_in_bytes(PoisonReasons)
+ llvm::capacity_in_bytes(CommentHandlers);
@@ -304,7 +313,7 @@ Preprocessor::macro_end(bool IncludeExternalMacros) const {
ExternalSource->ReadDefinedMacros();
}
- return Macros.end();
+ return CurSubmoduleState->Macros.end();
}
/// \brief Compares macro tokens with a specified token value sequence.
@@ -321,11 +330,11 @@ StringRef Preprocessor::getLastMacroWithSpelling(
StringRef BestSpelling;
for (Preprocessor::macro_iterator I = macro_begin(), E = macro_end();
I != E; ++I) {
- if (!I->second->getMacroInfo()->isObjectLike())
- continue;
const MacroDirective::DefInfo
- Def = I->second->findDirectiveAtLoc(Loc, SourceMgr);
- if (!Def)
+ Def = I->second.findDirectiveAtLoc(Loc, SourceMgr);
+ if (!Def || !Def.getMacroInfo())
+ continue;
+ if (!Def.getMacroInfo()->isObjectLike())
continue;
if (!MacroDefinitionEquals(Def.getMacroInfo(), Tokens))
continue;
@@ -584,6 +593,23 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) {
Diag(Identifier,it->second) << Identifier.getIdentifierInfo();
}
+/// \brief Returns a diagnostic message kind for reporting a future keyword as
+/// appropriate for the identifier and specified language.
+static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
+ const LangOptions &LangOpts) {
+ assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
+
+ if (LangOpts.CPlusPlus)
+ return llvm::StringSwitch<diag::kind>(II.getName())
+#define CXX11_KEYWORD(NAME, FLAGS) \
+ .Case(#NAME, diag::warn_cxx11_keyword)
+#include "clang/Basic/TokenKinds.def"
+ ;
+
+ llvm_unreachable(
+ "Keyword not known to come from a newer Standard or proposed Standard");
+}
+
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier. This callback looks up the identifier in the map and/or
/// potentially macro expands it or turns it into a named token (like 'for').
@@ -622,8 +648,9 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
}
// If this is a macro to be expanded, do it.
- if (MacroDirective *MD = getMacroDirective(&II)) {
- MacroInfo *MI = MD->getMacroInfo();
+ if (MacroDefinition MD = getMacroDefinition(&II)) {
+ auto *MI = MD.getMacroInfo();
+ assert(MI && "macro definition with no macro info?");
if (!DisableMacroExpansion) {
if (!Identifier.isExpandDisabled() && MI->isEnabled()) {
// C99 6.10.3p10: If the preprocessing token immediately after the
@@ -641,15 +668,16 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
}
}
- // If this identifier is a keyword in C++11, produce a warning. Don't warn if
- // we're not considering macro expansion, since this identifier might be the
- // name of a macro.
+ // If this identifier is a keyword in a newer Standard or proposed Standard,
+ // produce a warning. Don't warn if we're not considering macro expansion,
+ // since this identifier might be the name of a macro.
// FIXME: This warning is disabled in cases where it shouldn't be, like
// "#define constexpr constexpr", "int constexpr;"
- if (II.isCXX11CompatKeyword() && !DisableMacroExpansion) {
- Diag(Identifier, diag::warn_cxx11_keyword) << II.getName();
+ if (II.isFutureCompatKeyword() && !DisableMacroExpansion) {
+ Diag(Identifier, getFutureCompatDiagKind(II, getLangOpts()))
+ << II.getName();
// Don't diagnose this keyword again in this translation unit.
- II.setIsCXX11CompatKeyword(false);
+ II.setIsFutureCompatKeyword(false);
}
// C++ 2.11p2: If this is an alternative representation of a C++ operator,
@@ -748,16 +776,36 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
// If we have a non-empty module path, load the named module.
if (!ModuleImportPath.empty()) {
Module *Imported = nullptr;
- if (getLangOpts().Modules)
+ if (getLangOpts().Modules) {
Imported = TheModuleLoader.loadModule(ModuleImportLoc,
ModuleImportPath,
- Module::MacrosVisible,
+ Module::Hidden,
/*IsIncludeDirective=*/false);
+ if (Imported)
+ makeModuleVisible(Imported, ModuleImportLoc);
+ }
if (Callbacks && (getLangOpts().Modules || getLangOpts().DebuggerSupport))
Callbacks->moduleImport(ModuleImportLoc, ModuleImportPath, Imported);
}
}
+void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc) {
+ CurSubmoduleState->VisibleModules.setVisible(
+ M, Loc, [](Module *) {},
+ [&](ArrayRef<Module *> Path, Module *Conflict, StringRef Message) {
+ // FIXME: Include the path in the diagnostic.
+ // FIXME: Include the import location for the conflicting module.
+ Diag(ModuleImportLoc, diag::warn_module_conflict)
+ << Path[0]->getFullModuleName()
+ << Conflict->getFullModuleName()
+ << Message;
+ });
+
+ // Add this module to the imports list of the currently-built submodule.
+ if (!BuildingSubmoduleStack.empty() && M != BuildingSubmoduleStack.back().M)
+ BuildingSubmoduleStack.back().M->Imports.insert(M);
+}
+
bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String,
const char *DiagnosticTag,
bool AllowMacroExpansion) {
diff --git a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
index 3bac889..cd8a27e 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
@@ -64,12 +64,13 @@ void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
if (RequestLen < ScratchBufSize)
RequestLen = ScratchBufSize;
+ // Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file
+ // deterministically.
std::unique_ptr<llvm::MemoryBuffer> OwnBuf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
llvm::MemoryBuffer &Buf = *OwnBuf;
FileID FID = SourceMgr.createFileID(std::move(OwnBuf));
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf.getBufferStart());
- BytesUsed = 1;
- CurBuffer[0] = '0'; // Start out with a \0 for cleanliness.
+ BytesUsed = 0;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
index 0832749..27b4eab 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
@@ -178,20 +178,20 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
if (ConcatInfo & aci_avoid_equal) {
// If the next token is '=' or '==', avoid concatenation.
- if (Tok.is(tok::equal) || Tok.is(tok::equalequal))
+ if (Tok.isOneOf(tok::equal, tok::equalequal))
return true;
ConcatInfo &= ~aci_avoid_equal;
}
if (Tok.isAnnotation()) {
// Modules annotation can show up when generated automatically for includes.
- assert((Tok.is(tok::annot_module_include) ||
- Tok.is(tok::annot_module_begin) ||
- Tok.is(tok::annot_module_end)) &&
+ assert(Tok.isOneOf(tok::annot_module_include, tok::annot_module_begin,
+ tok::annot_module_end) &&
"unexpected annotation in AvoidConcat");
ConcatInfo = 0;
}
- if (ConcatInfo == 0) return false;
+ if (ConcatInfo == 0)
+ return false;
// Basic algorithm: we look at the first character of the second token, and
// determine whether it, if appended to the first token, would form (or
@@ -238,11 +238,11 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
if (Tok.is(tok::numeric_constant))
return GetFirstChar(PP, Tok) != '.';
- if (Tok.getIdentifierInfo() || Tok.is(tok::wide_string_literal) ||
- Tok.is(tok::utf8_string_literal) || Tok.is(tok::utf16_string_literal) ||
- Tok.is(tok::utf32_string_literal) || Tok.is(tok::wide_char_constant) ||
- Tok.is(tok::utf8_char_constant) || Tok.is(tok::utf16_char_constant) ||
- Tok.is(tok::utf32_char_constant))
+ if (Tok.getIdentifierInfo() ||
+ Tok.isOneOf(tok::wide_string_literal, tok::utf8_string_literal,
+ tok::utf16_string_literal, tok::utf32_string_literal,
+ tok::wide_char_constant, tok::utf8_char_constant,
+ tok::utf16_char_constant, tok::utf32_char_constant))
return true;
// If this isn't identifier + string, we're done.
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index 5f4705e..e7512fa 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -185,7 +185,7 @@ void TokenLexer::ExpandFunctionArguments() {
if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace())
NextTokGetsSpace = true;
- if (CurTok.is(tok::hash) || CurTok.is(tok::hashat)) {
+ if (CurTok.isOneOf(tok::hash, tok::hashat)) {
int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo());
assert(ArgNo != -1 && "Token following # is not an argument?");
@@ -521,6 +521,13 @@ bool TokenLexer::Lex(Token &Tok) {
/// are more ## after it, chomp them iteratively. Return the result as Tok.
/// If this returns true, the caller should immediately return the token.
bool TokenLexer::PasteTokens(Token &Tok) {
+ // MSVC: If previous token was pasted, this must be a recovery from an invalid
+ // paste operation. Ignore spaces before this token to mimic MSVC output.
+ // Required for generating valid UUID strings in some MS headers.
+ if (PP.getLangOpts().MicrosoftExt && (CurToken >= 2) &&
+ Tokens[CurToken - 2].is(tok::hashhash))
+ Tok.clearFlag(Token::LeadingSpace);
+
SmallString<128> Buffer;
const char *ResultTokStrPtr = nullptr;
SourceLocation StartLoc = Tok.getLocation();
@@ -637,7 +644,7 @@ bool TokenLexer::PasteTokens(Token &Tok) {
// disabling it.
PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::ext_pp_bad_paste_ms
: diag::err_pp_bad_paste)
- << Buffer.str();
+ << Buffer;
}
// An error has occurred so exit loop.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 59b491a..ab1f97d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -26,12 +26,10 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
AttributeList *AccessAttrs,
ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo,
- const VirtSpecifiers& VS,
- FunctionDefinitionKind DefinitionKind,
- ExprResult& Init) {
+ const VirtSpecifiers& VS,
+ SourceLocation PureSpecLoc) {
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||
- Tok.is(tok::equal)) &&
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) &&
"Current token not a '{', ':', '=', or 'try'!");
MultiTemplateParamsArg TemplateParams(
@@ -40,7 +38,6 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
NamedDecl *FnD;
- D.setFunctionDefinitionKind(DefinitionKind);
if (D.getDeclSpec().isFriendSpecified())
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
TemplateParams);
@@ -50,12 +47,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
VS, ICIS_NoInit);
if (FnD) {
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs);
- bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType();
- if (Init.isUsable())
- Actions.AddInitializerToDecl(FnD, Init.get(), false,
- TypeSpecContainsAuto);
- else
- Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto);
+ if (PureSpecLoc.isValid())
+ Actions.ActOnPureSpecifier(FnD, PureSpecLoc);
}
}
@@ -71,17 +64,24 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
bool Delete = false;
SourceLocation KWLoc;
+ SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_deleted_function
: diag::ext_deleted_function);
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
+ if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
+ DeclAsFunction->setRangeEnd(KWEndLoc);
+ }
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_defaulted_function
: diag::ext_defaulted_function);
Actions.SetDeclDefaulted(FnD, KWLoc);
+ if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
+ DeclAsFunction->setRangeEnd(KWEndLoc);
+ }
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
}
@@ -97,12 +97,12 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
return FnD;
}
-
+
// In delayed template parsing mode, if we are within a class template
// or if we are about to parse function member template then consume
// the tokens and store them for parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing &&
- DefinitionKind == FDK_Definition &&
+ D.getFunctionDefinitionKind() == FDK_Definition &&
!D.getDeclSpec().isConstexprSpecified() &&
!(FnD && FnD->getAsFunction() &&
FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
@@ -186,7 +186,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
/// declaration. Now lex its initializer and store its tokens for parsing
/// after the class is complete.
void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
- assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) &&
+ assert(Tok.isOneOf(tok::l_brace, tok::equal) &&
"Current token not a '{' or '='!");
LateParsedMemberInitializer *MI =
@@ -306,9 +306,10 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
Scope::FunctionDeclarationScope | Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+ auto Param = cast<ParmVarDecl>(LM.DefaultArgs[I].Param);
// Introduce the parameter into scope.
- Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
- LM.DefaultArgs[I].Param);
+ bool HasUnparsed = Param->hasUnparsedDefaultArg();
+ Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param);
if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
// Mark the end of the default argument so that we know when to stop when
// we parse it later on.
@@ -316,9 +317,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Token DefArgEnd;
DefArgEnd.startToken();
DefArgEnd.setKind(tok::eof);
- DefArgEnd.setLocation(LastDefaultArgToken.getLocation().getLocWithOffset(
- LastDefaultArgToken.getLength()));
- DefArgEnd.setEofData(LM.DefaultArgs[I].Param);
+ DefArgEnd.setLocation(LastDefaultArgToken.getEndLoc());
+ DefArgEnd.setEofData(Param);
Toks->push_back(DefArgEnd);
// Parse the default argument from its saved token stream.
@@ -336,7 +336,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// used.
EnterExpressionEvaluationContext Eval(Actions,
Sema::PotentiallyEvaluatedIfUsed,
- LM.DefaultArgs[I].Param);
+ Param);
ExprResult DefArgResult;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
@@ -346,11 +346,9 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
DefArgResult = ParseAssignmentExpression();
DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
if (DefArgResult.isInvalid()) {
- Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param,
- EqualLoc);
+ Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
} else {
- if (Tok.isNot(tok::eof) ||
- Tok.getEofData() != LM.DefaultArgs[I].Param) {
+ if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {
// The last two tokens are the terminator and the saved value of
// Tok; the last token in the default argument is the one before
// those.
@@ -359,7 +357,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
<< SourceRange(Tok.getLocation(),
(*Toks)[Toks->size() - 3].getLocation());
}
- Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+ Actions.ActOnParamDefaultArgument(Param, EqualLoc,
DefArgResult.get());
}
@@ -368,11 +366,21 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
while (Tok.isNot(tok::eof))
ConsumeAnyToken();
- if (Tok.is(tok::eof) && Tok.getEofData() == LM.DefaultArgs[I].Param)
+ if (Tok.is(tok::eof) && Tok.getEofData() == Param)
ConsumeAnyToken();
delete Toks;
LM.DefaultArgs[I].Toks = nullptr;
+ } else if (HasUnparsed) {
+ assert(Param->hasInheritedDefaultArg());
+ FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
+ ParmVarDecl *OldParam = Old->getParamDecl(I);
+ assert (!OldParam->hasUnparsedDefaultArg());
+ if (OldParam->hasUninstantiatedDefaultArg())
+ Param->setUninstantiatedDefaultArg(
+ Param->getUninstantiatedDefaultArg());
+ else
+ Param->setDefaultArg(OldParam->getInit());
}
}
@@ -383,9 +391,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Token ExceptionSpecEnd;
ExceptionSpecEnd.startToken();
ExceptionSpecEnd.setKind(tok::eof);
- ExceptionSpecEnd.setLocation(
- LastExceptionSpecToken.getLocation().getLocWithOffset(
- LastExceptionSpecToken.getLength()));
+ ExceptionSpecEnd.setLocation(LastExceptionSpecToken.getEndLoc());
ExceptionSpecEnd.setEofData(LM.Method);
Toks->push_back(ExceptionSpecEnd);
@@ -490,8 +496,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
Token BodyEnd;
BodyEnd.startToken();
BodyEnd.setKind(tok::eof);
- BodyEnd.setLocation(
- LastBodyToken.getLocation().getLocWithOffset(LastBodyToken.getLength()));
+ BodyEnd.setLocation(LastBodyToken.getEndLoc());
BodyEnd.setEofData(LM.D);
LM.Toks.push_back(BodyEnd);
// Append the current token at the end of the new token stream so that it
@@ -501,7 +506,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)
&& "Inline method not starting with '{', ':' or 'try'");
// Parse the method body. Function body parsing code is similar enough
@@ -816,7 +821,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
}
}
- if (Tok.is(tok::identifier) || Tok.is(tok::kw_template)) {
+ if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
Toks.push_back(Tok);
ConsumeToken();
} else if (Tok.is(tok::code_completion)) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 4d05e16..f46af88 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -285,7 +285,7 @@ unsigned Parser::ParseAttributeArgsCommon(
if (AttrKind == AttributeList::UnknownAttribute ||
AttrKind == AttributeList::IgnoredAttribute) {
const Token &Next = NextToken();
- IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma);
+ IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
}
if (IsIdentifierArg)
@@ -365,7 +365,8 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
// These may refer to the function arguments, but need to be parsed early to
// participate in determining whether it's a redeclaration.
std::unique_ptr<ParseScope> PrototypeScope;
- if (AttrName->isStr("enable_if") && D && D->isFunctionDeclarator()) {
+ if (normalizeAttrName(AttrName->getName()) == "enable_if" &&
+ D && D->isFunctionDeclarator()) {
DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope |
Scope::FunctionDeclarationScope |
@@ -529,64 +530,72 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
/// [MS] extended-decl-modifier-seq:
/// extended-decl-modifier[opt]
/// extended-decl-modifier extended-decl-modifier-seq
-void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
+void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End) {
+ assert((getLangOpts().MicrosoftExt || getLangOpts().Borland ||
+ getLangOpts().CUDA) &&
+ "Incorrect language options for parsing __declspec");
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
- ConsumeToken();
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
- tok::r_paren))
- return;
-
- // An empty declspec is perfectly legal and should not warn. Additionally,
- // you can specify multiple attributes per declspec.
- while (Tok.isNot(tok::r_paren)) {
- // Attribute not present.
- if (TryConsumeToken(tok::comma))
- continue;
-
- // We expect either a well-known identifier or a generic string. Anything
- // else is a malformed declspec.
- bool IsString = Tok.getKind() == tok::string_literal ? true : false;
- if (!IsString && Tok.getKind() != tok::identifier &&
- Tok.getKind() != tok::kw_restrict) {
- Diag(Tok, diag::err_ms_declspec_type);
- T.skipToEnd();
+ while (Tok.is(tok::kw___declspec)) {
+ ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
+ tok::r_paren))
return;
- }
- IdentifierInfo *AttrName;
- SourceLocation AttrNameLoc;
- if (IsString) {
- SmallString<8> StrBuffer;
- bool Invalid = false;
- StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
- if (Invalid) {
+ // An empty declspec is perfectly legal and should not warn. Additionally,
+ // you can specify multiple attributes per declspec.
+ while (Tok.isNot(tok::r_paren)) {
+ // Attribute not present.
+ if (TryConsumeToken(tok::comma))
+ continue;
+
+ // We expect either a well-known identifier or a generic string. Anything
+ // else is a malformed declspec.
+ bool IsString = Tok.getKind() == tok::string_literal;
+ if (!IsString && Tok.getKind() != tok::identifier &&
+ Tok.getKind() != tok::kw_restrict) {
+ Diag(Tok, diag::err_ms_declspec_type);
T.skipToEnd();
return;
}
- AttrName = PP.getIdentifierInfo(Str);
- AttrNameLoc = ConsumeStringToken();
- } else {
- AttrName = Tok.getIdentifierInfo();
- AttrNameLoc = ConsumeToken();
- }
- bool AttrHandled = false;
+ IdentifierInfo *AttrName;
+ SourceLocation AttrNameLoc;
+ if (IsString) {
+ SmallString<8> StrBuffer;
+ bool Invalid = false;
+ StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
+ if (Invalid) {
+ T.skipToEnd();
+ return;
+ }
+ AttrName = PP.getIdentifierInfo(Str);
+ AttrNameLoc = ConsumeStringToken();
+ } else {
+ AttrName = Tok.getIdentifierInfo();
+ AttrNameLoc = ConsumeToken();
+ }
+
+ bool AttrHandled = false;
- // Parse attribute arguments.
- if (Tok.is(tok::l_paren))
- AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
- else if (AttrName->getName() == "property")
- // The property attribute must have an argument list.
- Diag(Tok.getLocation(), diag::err_expected_lparen_after)
- << AttrName->getName();
+ // Parse attribute arguments.
+ if (Tok.is(tok::l_paren))
+ AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
+ else if (AttrName->getName() == "property")
+ // The property attribute must have an argument list.
+ Diag(Tok.getLocation(), diag::err_expected_lparen_after)
+ << AttrName->getName();
- if (!AttrHandled)
- Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Declspec);
+ if (!AttrHandled)
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Declspec);
+ }
+ T.consumeClose();
+ if (End)
+ *End = T.getCloseLocation();
}
- T.consumeClose();
}
void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
@@ -679,6 +688,28 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
AttributeList::AS_Keyword);
}
+void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
+ // Treat these like attributes, even though they're type specifiers.
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified: {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ if (!getLangOpts().ObjC1)
+ Diag(AttrNameLoc, diag::ext_nullability)
+ << AttrName;
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Keyword);
+ break;
+ }
+ default:
+ return;
+ }
+ }
+}
+
static bool VersionNumberSeparator(const char Separator) {
return (Separator == '.' || Separator == '_');
}
@@ -1360,6 +1391,46 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
}
}
+// As an exception to the rule, __declspec(align(...)) before the
+// class-key affects the type instead of the variable.
+void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS,
+ Sema::TagUseKind TUK) {
+ if (TUK == Sema::TUK_Reference)
+ return;
+
+ ParsedAttributes &PA = DS.getAttributes();
+ AttributeList *AL = PA.getList();
+ AttributeList *Prev = nullptr;
+ while (AL) {
+ AttributeList *Next = AL->getNext();
+
+ // We only consider attributes using the appropriate '__declspec' spelling,
+ // this behavior doesn't extend to any other spellings.
+ if (AL->getKind() == AttributeList::AT_Aligned &&
+ AL->isDeclspecAttribute()) {
+ // Stitch the attribute into the tag's attribute list.
+ AL->setNext(nullptr);
+ Attrs.add(AL);
+
+ // Remove the attribute from the variable's attribute list.
+ if (Prev) {
+ // Set the last variable attribute's next attribute to be the attribute
+ // after the current one.
+ Prev->setNext(Next);
+ } else {
+ // Removing the head of the list requires us to reset the head to the
+ // next attribute.
+ PA.set(Next);
+ }
+ } else {
+ Prev = AL;
+ }
+
+ AL = Next;
+ }
+}
+
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
/// 'Context' should be a Declarator::TheContext value. This returns the
@@ -1551,7 +1622,7 @@ void Parser::SkipMalformedDecl() {
// a malformed class or function definition or similar.
ConsumeBrace();
SkipUntil(tok::r_brace);
- if (Tok.is(tok::comma) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try)) {
+ if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {
// This declaration isn't over yet. Keep skipping.
continue;
}
@@ -1657,7 +1728,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// and we don't have any other declarators in this declaration.
bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
MaybeParseGNUAttributes(D, &LateParsedAttrs);
- Fixit &= Tok.is(tok::semi) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try);
+ Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);
Diag(Loc, diag::err_c11_noreturn_misplaced)
<< (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
@@ -1691,11 +1762,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
if (isDeclarationSpecifier()) {
- // If there is an invalid declaration specifier right after the function
- // prototype, then we must be in a missing semicolon case where this isn't
- // actually a body. Just fall through into the code that handles it as a
- // prototype, and let the top-level code handle the erroneous declspec
- // where it would otherwise expect a comma or semicolon.
+ // If there is an invalid declaration specifier right after the
+ // function prototype, then we must be in a missing semicolon case
+ // where this isn't actually a body. Just fall through into the code
+ // that handles it as a prototype, and let the top-level code handle
+ // the erroneous declspec where it would otherwise expect a comma or
+ // semicolon.
} else {
Diag(Tok, diag::err_expected_fn_body);
SkipUntil(tok::semi);
@@ -1993,7 +2065,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
}
- if (ParseExpressionList(Exprs, CommaLocs)) {
+ if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ Actions.CodeCompleteConstructor(getCurScope(),
+ cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(),
+ ThisDecl->getLocation(), Exprs);
+ })) {
Actions.ActOnInitializerError(ThisDecl);
SkipUntil(tok::r_paren, StopAtSemi);
@@ -2069,8 +2145,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
Diag(Tok, diag::err_expected_type);
DS.SetTypeSpecError();
- } else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
- !DS.hasAttributes()) {
+ } else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) {
Diag(Tok, diag::err_typename_requires_specqual);
if (!DS.hasTypeSpecifier())
DS.SetTypeSpecError();
@@ -2098,7 +2173,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
}
// Issue diagnostic and remove constexpr specfier if present.
- if (DS.isConstexprSpecified()) {
+ if (DS.isConstexprSpecified() && DSC != DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
DS.ClearConstexprSpec();
}
@@ -2123,9 +2198,9 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
/// int (x)
///
static bool isValidAfterIdentifierInDeclarator(const Token &T) {
- return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) ||
- T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) ||
- T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon);
+ return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,
+ tok::comma, tok::equal, tok::kw_asm, tok::l_brace,
+ tok::colon);
}
@@ -2385,7 +2460,7 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start,
/// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'
void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {
- assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) &&
+ assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&
"Not an alignment-specifier!");
IdentifierInfo *KWName = Tok.getIdentifierInfo();
@@ -2428,8 +2503,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
if (getLangOpts().CPlusPlus &&
- (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
+ tok::annot_template_id) &&
TryAnnotateCXXScopeToken(EnteringContext)) {
SkipMalformedDecl();
return true;
@@ -2442,7 +2517,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
// Determine whether the following tokens could possibly be a
// declarator.
bool MightBeDeclarator = true;
- if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {
// A declarator-id can't start with 'typename'.
MightBeDeclarator = false;
} else if (AfterScope.is(tok::annot_template_id)) {
@@ -2457,9 +2532,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
// These tokens cannot come after the declarator-id in a
// simple-declaration, and are likely to come after a type-specifier.
- if (Next.is(tok::star) || Next.is(tok::amp) || Next.is(tok::ampamp) ||
- Next.is(tok::identifier) || Next.is(tok::annot_cxxscope) ||
- Next.is(tok::coloncolon)) {
+ if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,
+ tok::annot_cxxscope, tok::coloncolon)) {
// Missing a semicolon.
MightBeDeclarator = false;
} else if (HasScope) {
@@ -2528,6 +2602,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
/// [C11] alignment-specifier declaration-specifiers[opt]
/// [GNU] attributes declaration-specifiers[opt]
/// [Clang] '__module_private__' declaration-specifiers[opt]
+/// [ObjC1] '__kindof' declaration-specifiers[opt]
///
/// storage-class-specifier: [C99 6.7.1]
/// 'typedef'
@@ -2564,7 +2639,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
- const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
+ // We use Sema's policy to get bool macros right.
+ const PrintingPolicy &Policy = Actions.getPrintingPolicy();
while (1) {
bool isInvalid = false;
bool isStorageClass = false;
@@ -2811,12 +2887,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken(); // The typename
- // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
- // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface.
- if (Tok.is(tok::less) && getLangOpts().ObjC1)
- ParseObjCProtocolQualifiers(DS);
-
continue;
}
@@ -2866,14 +2936,27 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.isTypeAltiVecVector())
goto DoneWithDeclSpec;
+ if (DSContext == DSC_objc_method_result && isObjCInstancetype()) {
+ ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
+ assert(TypeRep);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DiagID, TypeRep, Policy);
+ if (isInvalid)
+ break;
+
+ DS.SetRangeEnd(Loc);
+ ConsumeToken();
+ continue;
+ }
+
ParsedType TypeRep =
Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), getCurScope());
// MSVC: If we weren't able to parse a default template argument, and it's
- // just a simple identifier, create a DependentNameType. This will allow us
- // to defer the name lookup to template instantiation time, as long we forge a
- // NestedNameSpecifier for the current context.
+ // just a simple identifier, create a DependentNameType. This will allow
+ // us to defer the name lookup to template instantiation time, as long we
+ // forge a NestedNameSpecifier for the current context.
if (!TypeRep && DSContext == DSC_template_type_arg &&
getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) {
TypeRep = Actions.ActOnDelayedDefaultTemplateArg(
@@ -2909,11 +2992,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken(); // The identifier
- // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
- // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface.
- if (Tok.is(tok::less) && getLangOpts().ObjC1)
- ParseObjCProtocolQualifiers(DS);
+ // Objective-C supports type arguments and protocol references
+ // following an Objective-C object or object pointer
+ // type. Handle either one of them.
+ if (Tok.is(tok::less) && getLangOpts().ObjC1) {
+ SourceLocation NewEndLoc;
+ TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(
+ Loc, TypeRep, /*consumeLastToken=*/true,
+ NewEndLoc);
+ if (NewTypeRep.isUsable()) {
+ DS.UpdateTypeRep(NewTypeRep.get());
+ DS.SetRangeEnd(NewEndLoc);
+ }
+ }
// Need to support trailing type qualifiers (e.g. "id<p> const").
// If a type specifier follows, it will be diagnosed elsewhere.
@@ -2950,7 +3041,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Microsoft declspec support.
case tok::kw___declspec:
- ParseMicrosoftDeclSpec(DS.getAttributes());
+ ParseMicrosoftDeclSpecs(DS.getAttributes());
continue;
// Microsoft single token adornments.
@@ -2987,6 +3078,20 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ParseOpenCLAttributes(DS.getAttributes());
continue;
+ // Nullability type specifiers.
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified:
+ ParseNullabilityTypeSpecifiers(DS.getAttributes());
+ continue;
+
+ // Objective-C 'kindof' types.
+ case tok::kw___kindof:
+ DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
+ nullptr, 0, AttributeList::AS_Keyword);
+ (void)ConsumeToken();
+ continue;
+
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
@@ -3097,6 +3202,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
break;
+ // concept
+ case tok::kw_concept:
+ isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID);
+ break;
+
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
@@ -3318,10 +3428,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.hasTypeSpecifier() || !getLangOpts().ObjC1)
goto DoneWithDeclSpec;
- if (!ParseObjCProtocolQualifiers(DS))
- Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
- << FixItHint::CreateInsertion(Loc, "id")
- << SourceRange(Loc, DS.getSourceRange().getEnd());
+ SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation EndLoc;
+ TypeResult Type = parseObjCProtocolQualifierType(EndLoc);
+ if (Type.isUsable()) {
+ if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc,
+ PrevSpec, DiagID, Type.get(),
+ Actions.getASTContext().getPrintingPolicy()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+
+ DS.SetRangeEnd(EndLoc);
+ } else {
+ DS.SetTypeSpecError();
+ }
// Need to support trailing type qualifiers (e.g. "id<p> const").
// If a type specifier follows, it will be diagnosed elsewhere.
@@ -3594,16 +3713,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
MaybeParseCXX11Attributes(attrs);
-
- // If declspecs exist after tag, parse them.
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
SourceLocation ScopedEnumKWLoc;
bool IsScopedUsingClassTag = false;
// In C++11, recognize 'enum class' and 'enum struct'.
- if (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct)) {
+ if (Tok.isOneOf(tok::kw_class, tok::kw_struct)) {
Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum
: diag::ext_scoped_enum);
IsScopedUsingClassTag = Tok.is(tok::kw_class);
@@ -3616,8 +3732,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// They are allowed afterwards, though.
MaybeParseGNUAttributes(attrs);
MaybeParseCXX11Attributes(attrs);
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
}
// C++11 [temp.explicit]p12:
@@ -3644,11 +3759,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// if a fixed underlying type is allowed.
ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ CXXScopeSpec Spec;
+ if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(),
/*EnteringContext=*/true))
return;
- if (SS.isSet() && Tok.isNot(tok::identifier)) {
+ if (Spec.isSet() && Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
if (Tok.isNot(tok::l_brace)) {
// Has no name and is not a definition.
@@ -3657,6 +3773,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
}
+
+ SS = Spec;
}
// Must have either 'enum name' or 'enum {...}'.
@@ -3842,6 +3960,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
+ Sema::SkipBodyInfo SkipBody;
+ if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) &&
+ NextToken().is(tok::identifier))
+ SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),
+ NextToken().getIdentifierInfo(),
+ NextToken().getLocation());
+
bool Owned = false;
bool IsDependent = false;
const char *PrevSpec = nullptr;
@@ -3851,7 +3978,22 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
AS, DS.getModulePrivateSpecLoc(), TParams,
Owned, IsDependent, ScopedEnumKWLoc,
IsScopedUsingClassTag, BaseType,
- DSC == DSC_type_specifier);
+ DSC == DSC_type_specifier, &SkipBody);
+
+ if (SkipBody.ShouldSkip) {
+ assert(TUK == Sema::TUK_Definition && "can only skip a definition");
+
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
+ T.skipToEnd();
+
+ if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
+ NameLoc.isValid() ? NameLoc : StartLoc,
+ PrevSpec, DiagID, TagDecl, Owned,
+ Actions.getASTContext().getPrintingPolicy()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+ return;
+ }
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
@@ -3923,6 +4065,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
Diag(Tok, diag::error_empty_enum);
SmallVector<Decl *, 32> EnumConstantDecls;
+ SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
Decl *LastEnumConstDecl = nullptr;
@@ -3953,7 +4096,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
SourceLocation EqualLoc;
ExprResult AssignedVal;
- ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
+ EnumAvailabilityDiags.emplace_back(*this);
if (TryConsumeToken(tok::equal, EqualLoc)) {
AssignedVal = ParseConstantExpression();
@@ -3967,7 +4110,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
IdentLoc, Ident,
attrs.getList(), EqualLoc,
AssignedVal.get());
- PD.complete(EnumConstDecl);
+ EnumAvailabilityDiags.back().done();
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
@@ -4023,6 +4166,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
getCurScope(),
attrs.getList());
+ // Now handle enum constant availability diagnostics.
+ assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
+ for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {
+ ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
+ EnumAvailabilityDiags[i].redelay();
+ PD.complete(EnumConstantDecls[i]);
+ }
+
EnumScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,
T.getCloseLocation());
@@ -4199,6 +4350,12 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___pascal:
case tok::kw___unaligned:
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified:
+
+ case tok::kw___kindof:
+
case tok::kw___private:
case tok::kw___local:
case tok::kw___global:
@@ -4344,6 +4501,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::annot_decltype:
case tok::kw_constexpr:
+ // C++ Concepts TS - concept
+ case tok::kw_concept:
+
// C11 _Atomic
case tok::kw__Atomic:
return true;
@@ -4372,6 +4532,12 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___pascal:
case tok::kw___unaligned:
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified:
+
+ case tok::kw___kindof:
+
case tok::kw___private:
case tok::kw___local:
case tok::kw___global:
@@ -4397,7 +4563,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
}
// Parse the constructor name.
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+ if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) {
// We already know that we have a constructor name; just consume
// the token.
ConsumeToken();
@@ -4601,6 +4767,21 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
continue;
}
goto DoneWithTypeQuals;
+
+ // Nullability type specifiers.
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified:
+ ParseNullabilityTypeSpecifiers(DS.getAttributes());
+ continue;
+
+ // Objective-C 'kindof' types.
+ case tok::kw___kindof:
+ DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
+ nullptr, 0, AttributeList::AS_Keyword);
+ (void)ConsumeToken();
+ continue;
+
case tok::kw___attribute:
if (AttrReqs & AR_GNUAttributesParsedAndRejected)
// When GNU attributes are expressly forbidden, diagnose their usage.
@@ -4773,7 +4954,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
DS.getConstSpecLoc(),
DS.getVolatileSpecLoc(),
- DS.getRestrictSpecLoc()),
+ DS.getRestrictSpecLoc(),
+ DS.getAtomicSpecLoc()),
DS.getAttributes(),
SourceLocation());
else
@@ -4916,7 +5098,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
if (D.getCXXScopeSpec().isValid()) {
- if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@@ -4953,8 +5136,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// the l_paren token.
}
- if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
- Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+ if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
+ tok::tilde)) {
// We found something that indicates the start of an unqualified-id.
// Parse that unqualified-id.
bool AllowConstructorName;
@@ -4968,6 +5151,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
AllowConstructorName = (D.getContext() == Declarator::MemberContext);
SourceLocation TemplateKWLoc;
+ bool HadScope = D.getCXXScopeSpec().isValid();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true,
@@ -4981,6 +5165,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
} else {
+ // ParseUnqualifiedId might have parsed a scope specifier during error
+ // recovery. If it did so, enter that scope.
+ if (!HadScope && D.getCXXScopeSpec().isValid() &&
+ Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
+ DeclScopeObj.EnterDeclaratorScope();
+
// Parsed the unqualified-id; update range information and move along.
if (D.getSourceRange().getBegin().isInvalid())
D.SetRangeBegin(D.getName().getSourceRange().getBegin());
@@ -5022,7 +5213,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// If there was an error parsing parenthesized declarator, declarator
// scope may have been entered before. Don't do it again.
if (!D.isInvalidType() &&
- Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@@ -5048,7 +5240,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
<< (D.getDeclSpec().isEmpty() ? SourceRange()
: D.getDeclSpec().getSourceRange());
} else if (getLangOpts().CPlusPlus) {
- if (Tok.is(tok::period) || Tok.is(tok::arrow))
+ if (Tok.isOneOf(tok::period, tok::arrow))
Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
else {
SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
@@ -5310,7 +5502,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
if (getLangOpts().CPlusPlus) {
// FIXME: Accept these components in any order, and produce fixits to
// correct the order if the user gets it wrong. Ideally we should deal
- // with the virt-specifier-seq and pure-specifier in the same way.
+ // with the pure-specifier in the same way.
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
@@ -5323,15 +5515,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}
// Parse ref-qualifier[opt].
- if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_ref_qualifier :
- diag::ext_ref_qualifier);
-
- RefQualifierIsLValueRef = Tok.is(tok::amp);
- RefQualifierLoc = ConsumeToken();
+ if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
EndLoc = RefQualifierLoc;
- }
// C++11 [expr.prim.general]p3:
// If a declaration declares a member function or member function
@@ -5427,6 +5612,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
FnAttrs, EndLoc);
}
+/// ParseRefQualifier - Parses a member function ref-qualifier. Returns
+/// true if a ref-qualifier is found.
+bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
+ SourceLocation &RefQualifierLoc) {
+ if (Tok.isOneOf(tok::amp, tok::ampamp)) {
+ Diag(Tok, getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_ref_qualifier :
+ diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ return true;
+ }
+ return false;
+}
+
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
/// identifier list form for a K&R-style function: void foo(a,b,c)
///
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index 87d9909..e347d4e 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -543,10 +543,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation IdLoc = ConsumeToken();
ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII);
Name.setConstructorName(Type, IdLoc, IdLoc);
- } else if (ParseUnqualifiedId(SS, /*EnteringContext=*/ false,
- /*AllowDestructorName=*/ true,
- /*AllowConstructorName=*/ true, ParsedType(),
- TemplateKWLoc, Name)) {
+ } else if (ParseUnqualifiedId(
+ SS, /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/NextToken().isNot(tok::equal),
+ ParsedType(), TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -558,6 +559,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Maybe this is an alias-declaration.
TypeResult TypeAlias;
bool IsAliasDecl = Tok.is(tok::equal);
+ Decl *DeclFromDeclSpec = nullptr;
if (IsAliasDecl) {
// If we had any misplaced attributes from earlier, this is where they
// should have been written.
@@ -612,10 +614,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SS.getRange());
- TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ?
- Declarator::AliasTemplateContext :
- Declarator::AliasDeclContext, AS, OwnedType,
- &Attrs);
+ TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind
+ ? Declarator::AliasTemplateContext
+ : Declarator::AliasDeclContext,
+ AS, &DeclFromDeclSpec, &Attrs);
+ if (OwnedType)
+ *OwnedType = DeclFromDeclSpec;
} else {
// C++11 attributes are not allowed on a using-declaration, but GNU ones
// are.
@@ -664,7 +668,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
TemplateParams ? TemplateParams->size() : 0);
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
UsingLoc, Name, Attrs.getList(),
- TypeAlias);
+ TypeAlias, DeclFromDeclSpec);
}
return Actions.ActOnUsingDeclaration(getCurScope(), AS,
@@ -682,7 +686,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
/// _Static_assert ( constant-expression , string-literal ) ;
///
Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
- assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) &&
+ assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&
"Not a static_assert declaration");
if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
@@ -750,7 +754,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
/// 'decltype' ( 'auto' ) [C++1y]
///
SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
- assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))
+ assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)
&& "Not a decltype specifier");
ExprResult Result;
@@ -796,7 +800,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
nullptr,/*IsDecltype=*/true);
- Result = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ Result =
+ Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
+ return E->hasPlaceholderType() ? ExprError() : E;
+ });
if (Result.isInvalid()) {
DS.SetTypeSpecError();
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
@@ -937,7 +944,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Parse decltype-specifier
// tok == kw_decltype is just error recovery, it can only happen when SS
// isn't empty
- if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) {
+ if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
if (SS.isNotEmpty())
Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)
<< FixItHint::CreateRemoval(SS.getRange());
@@ -1052,9 +1059,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
}
void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
- while (Tok.is(tok::kw___single_inheritance) ||
- Tok.is(tok::kw___multiple_inheritance) ||
- Tok.is(tok::kw___virtual_inheritance)) {
+ while (Tok.isOneOf(tok::kw___single_inheritance,
+ tok::kw___multiple_inheritance,
+ tok::kw___virtual_inheritance)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
@@ -1223,15 +1230,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParsedAttributesWithRange attrs(AttrFactory);
// If attributes exist after tag, parse them.
MaybeParseGNUAttributes(attrs);
-
- // If declspecs exist after tag, parse them.
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
// Parse inheritance specifiers.
- if (Tok.is(tok::kw___single_inheritance) ||
- Tok.is(tok::kw___multiple_inheritance) ||
- Tok.is(tok::kw___virtual_inheritance))
+ if (Tok.isOneOf(tok::kw___single_inheritance,
+ tok::kw___multiple_inheritance,
+ tok::kw___virtual_inheritance))
ParseMicrosoftInheritanceClassAttributes(attrs);
// If C++0x attributes exist here, parse them.
@@ -1247,55 +1251,55 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Tok.isNot(tok::identifier) &&
!Tok.isAnnotation() &&
Tok.getIdentifierInfo() &&
- (Tok.is(tok::kw___is_abstract) ||
- Tok.is(tok::kw___is_arithmetic) ||
- Tok.is(tok::kw___is_array) ||
- Tok.is(tok::kw___is_base_of) ||
- Tok.is(tok::kw___is_class) ||
- Tok.is(tok::kw___is_complete_type) ||
- Tok.is(tok::kw___is_compound) ||
- Tok.is(tok::kw___is_const) ||
- Tok.is(tok::kw___is_constructible) ||
- Tok.is(tok::kw___is_convertible) ||
- Tok.is(tok::kw___is_convertible_to) ||
- Tok.is(tok::kw___is_destructible) ||
- Tok.is(tok::kw___is_empty) ||
- Tok.is(tok::kw___is_enum) ||
- Tok.is(tok::kw___is_floating_point) ||
- Tok.is(tok::kw___is_final) ||
- Tok.is(tok::kw___is_function) ||
- Tok.is(tok::kw___is_fundamental) ||
- Tok.is(tok::kw___is_integral) ||
- Tok.is(tok::kw___is_interface_class) ||
- Tok.is(tok::kw___is_literal) ||
- Tok.is(tok::kw___is_lvalue_expr) ||
- Tok.is(tok::kw___is_lvalue_reference) ||
- Tok.is(tok::kw___is_member_function_pointer) ||
- Tok.is(tok::kw___is_member_object_pointer) ||
- Tok.is(tok::kw___is_member_pointer) ||
- Tok.is(tok::kw___is_nothrow_assignable) ||
- Tok.is(tok::kw___is_nothrow_constructible) ||
- Tok.is(tok::kw___is_nothrow_destructible) ||
- Tok.is(tok::kw___is_object) ||
- Tok.is(tok::kw___is_pod) ||
- Tok.is(tok::kw___is_pointer) ||
- Tok.is(tok::kw___is_polymorphic) ||
- Tok.is(tok::kw___is_reference) ||
- Tok.is(tok::kw___is_rvalue_expr) ||
- Tok.is(tok::kw___is_rvalue_reference) ||
- Tok.is(tok::kw___is_same) ||
- Tok.is(tok::kw___is_scalar) ||
- Tok.is(tok::kw___is_sealed) ||
- Tok.is(tok::kw___is_signed) ||
- Tok.is(tok::kw___is_standard_layout) ||
- Tok.is(tok::kw___is_trivial) ||
- Tok.is(tok::kw___is_trivially_assignable) ||
- Tok.is(tok::kw___is_trivially_constructible) ||
- Tok.is(tok::kw___is_trivially_copyable) ||
- Tok.is(tok::kw___is_union) ||
- Tok.is(tok::kw___is_unsigned) ||
- Tok.is(tok::kw___is_void) ||
- Tok.is(tok::kw___is_volatile)))
+ Tok.isOneOf(tok::kw___is_abstract,
+ tok::kw___is_arithmetic,
+ tok::kw___is_array,
+ tok::kw___is_base_of,
+ tok::kw___is_class,
+ tok::kw___is_complete_type,
+ tok::kw___is_compound,
+ tok::kw___is_const,
+ tok::kw___is_constructible,
+ tok::kw___is_convertible,
+ tok::kw___is_convertible_to,
+ tok::kw___is_destructible,
+ tok::kw___is_empty,
+ tok::kw___is_enum,
+ tok::kw___is_floating_point,
+ tok::kw___is_final,
+ tok::kw___is_function,
+ tok::kw___is_fundamental,
+ tok::kw___is_integral,
+ tok::kw___is_interface_class,
+ tok::kw___is_literal,
+ tok::kw___is_lvalue_expr,
+ tok::kw___is_lvalue_reference,
+ tok::kw___is_member_function_pointer,
+ tok::kw___is_member_object_pointer,
+ tok::kw___is_member_pointer,
+ tok::kw___is_nothrow_assignable,
+ tok::kw___is_nothrow_constructible,
+ tok::kw___is_nothrow_destructible,
+ tok::kw___is_object,
+ tok::kw___is_pod,
+ tok::kw___is_pointer,
+ tok::kw___is_polymorphic,
+ tok::kw___is_reference,
+ tok::kw___is_rvalue_expr,
+ tok::kw___is_rvalue_reference,
+ tok::kw___is_same,
+ tok::kw___is_scalar,
+ tok::kw___is_sealed,
+ tok::kw___is_signed,
+ tok::kw___is_standard_layout,
+ tok::kw___is_trivial,
+ tok::kw___is_trivially_assignable,
+ tok::kw___is_trivially_constructible,
+ tok::kw___is_trivially_copyable,
+ tok::kw___is_union,
+ tok::kw___is_unsigned,
+ tok::kw___is_void,
+ tok::kw___is_volatile))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
// and Clang. Therefore, when we see the token sequence "struct
@@ -1310,11 +1314,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// is a base-specifier-list.
ColonProtectionRAIIObject X(*this);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
+ CXXScopeSpec Spec;
+ bool HasValidSpec = true;
+ if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) {
DS.SetTypeSpecError();
- if (SS.isSet())
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
+ HasValidSpec = false;
+ }
+ if (Spec.isSet())
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) {
Diag(Tok, diag::err_expected) << tok::identifier;
+ HasValidSpec = false;
+ }
+ if (HasValidSpec)
+ SS = Spec;
}
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
@@ -1465,7 +1477,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
}
- if (Tok.is(tok::l_brace) || Tok.is(tok::colon))
+ if (Tok.isOneOf(tok::l_brace, tok::colon))
TUK = Sema::TUK_Definition;
else
TUK = Sema::TUK_Reference;
@@ -1539,6 +1551,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TypeResult TypeResult = true; // invalid
bool Owned = false;
+ Sema::SkipBodyInfo SkipBody;
if (TemplateId) {
// Explicit specialization, class template partial specialization,
// or explicit instantiation.
@@ -1625,7 +1638,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
*TemplateId, attrs.getList(),
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
: nullptr,
- TemplateParams ? TemplateParams->size() : 0));
+ TemplateParams ? TemplateParams->size() : 0),
+ &SkipBody);
}
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
@@ -1677,6 +1691,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams =
MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
SS, Name, NameLoc, attrs.getList(), AS,
@@ -1684,7 +1700,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams, Owned, IsDependent,
SourceLocation(), false,
clang::TypeResult(),
- DSC == DSC_type_specifier);
+ DSC == DSC_type_specifier,
+ &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -1700,7 +1717,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
assert(Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
isCXX11FinalKeyword());
- if (getLangOpts().CPlusPlus)
+ if (SkipBody.ShouldSkip)
+ SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,
+ TagOrTempResult.get());
+ else if (getLangOpts().CPlusPlus)
ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,
TagOrTempResult.get());
else
@@ -1882,51 +1902,40 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
/// the class definition.
void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
Decl *ThisDecl) {
- // We just declared a member function. If this member function
- // has any default arguments or an exception-specification, we'll need to
- // parse them later.
- LateParsedMethodDeclaration *LateMethod = nullptr;
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
+ // If there was a late-parsed exception-specification, we'll need a
+ // late parse
+ bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;
+
+ if (!NeedLateParse) {
+ // Look ahead to see if there are any default args
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
+ auto Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param);
+ if (Param->hasUnparsedDefaultArg()) {
+ NeedLateParse = true;
+ break;
+ }
+ }
+ }
- // If there was a late-parsed exception-specification, hold onto its tokens.
- if (FTI.getExceptionSpecType() == EST_Unparsed) {
+ if (NeedLateParse) {
// Push this method onto the stack of late-parsed method
// declarations.
- LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+ auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
- // Stash the exception-specification tokens in the late-pased mthod.
+ // Stash the exception-specification tokens in the late-pased method.
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
FTI.ExceptionSpecTokens = 0;
- // Reserve space for the parameters.
+ // Push tokens for each parameter. Those that do not have
+ // defaults will be NULL.
LateMethod->DefaultArgs.reserve(FTI.NumParams);
- }
-
- for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
- if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) {
- if (!LateMethod) {
- // Push this method onto the stack of late-parsed method
- // declarations.
- LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
- getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
- LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
-
- // Add all of the parameters prior to this one (they don't
- // have default arguments).
- LateMethod->DefaultArgs.reserve(FTI.NumParams);
- for (unsigned I = 0; I < ParamIdx; ++I)
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.Params[I].Param));
- }
-
- // Add this parameter to the list of parameters (it may or may
- // not have a default argument).
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
- FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
- }
+ FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
}
}
@@ -2019,7 +2028,7 @@ bool Parser::isCXX11FinalKeyword() const {
/// \brief Parse a C++ member-declarator up to, but not including, the optional
/// brace-or-equal-initializer or pure-specifier.
-void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
+bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
LateParsedAttrList &LateParsedAttrs) {
// member-declarator:
@@ -2037,10 +2046,13 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
BitfieldSize = ParseConstantExpression();
if (BitfieldSize.isInvalid())
SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- } else
+ } else {
ParseOptionalCXX11VirtSpecifierSeq(
VS, getCurrentClass().IsInterface,
DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
+ if (!VS.isUnset())
+ MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
+ }
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
@@ -2071,6 +2083,78 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
Diag(Attr->getLoc(), diag::warn_gcc_attribute_location);
Attr = Attr->getNext();
}
+ MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
+ }
+ }
+
+ // If this has neither a name nor a bit width, something has gone seriously
+ // wrong. Skip until the semi-colon or }.
+ if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
+ // If so, skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ return true;
+ }
+ return false;
+}
+
+/// \brief Look for declaration specifiers possibly occurring after C++11
+/// virt-specifier-seq and diagnose them.
+void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
+ Declarator &D,
+ VirtSpecifiers &VS) {
+ DeclSpec DS(AttrFactory);
+
+ // GNU-style and C++11 attributes are not allowed here, but they will be
+ // handled by the caller. Diagnose everything else.
+ ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
+ D.ExtendWithDeclSpec(DS);
+
+ if (D.isFunctionDeclarator()) {
+ auto &Function = D.getFunctionTypeInfo();
+ if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
+ auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
+ const char *FixItName,
+ SourceLocation SpecLoc,
+ unsigned* QualifierLoc) {
+ FixItHint Insertion;
+ if (DS.getTypeQualifiers() & TypeQual) {
+ if (!(Function.TypeQuals & TypeQual)) {
+ std::string Name(FixItName);
+ Name += " ";
+ Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name.c_str());
+ Function.TypeQuals |= TypeQual;
+ *QualifierLoc = SpecLoc.getRawEncoding();
+ }
+ Diag(SpecLoc, diag::err_declspec_after_virtspec)
+ << FixItName
+ << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
+ << FixItHint::CreateRemoval(SpecLoc)
+ << Insertion;
+ }
+ };
+ DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
+ &Function.ConstQualifierLoc);
+ DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
+ &Function.VolatileQualifierLoc);
+ DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
+ &Function.RestrictQualifierLoc);
+ }
+
+ // Parse ref-qualifiers.
+ bool RefQualifierIsLValueRef = true;
+ SourceLocation RefQualifierLoc;
+ if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
+ const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");
+ FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
+ Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;
+ Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
+
+ Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)
+ << (RefQualifierIsLValueRef ? "&" : "&&")
+ << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
+ << FixItHint::CreateRemoval(RefQualifierLoc)
+ << Insertion;
+ D.SetRangeEnd(RefQualifierLoc);
}
}
}
@@ -2137,8 +2221,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
- (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw___super))) {
+ Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) {
if (TryAnnotateCXXScopeToken())
MalformedTypeSpec = true;
@@ -2191,7 +2274,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// static_assert-declaration. A templated static_assert declaration is
// diagnosed in Parser::ParseSingleDeclarationAfterTemplate.
if (!TemplateInfo.Kind &&
- (Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert))) {
+ Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
SourceLocation DeclEnd;
ParseStaticAssertDeclaration(DeclEnd);
return;
@@ -2290,22 +2373,36 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
LateParsedAttrList LateParsedAttrs;
SourceLocation EqualLoc;
- bool HasInitializer = false;
- ExprResult Init;
+ SourceLocation PureSpecLoc;
+
+ auto TryConsumePureSpecifier = [&] (bool AllowDefinition) {
+ if (Tok.isNot(tok::equal))
+ return false;
+
+ auto &Zero = NextToken();
+ SmallString<8> Buffer;
+ if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 ||
+ PP.getSpelling(Zero, Buffer) != "0")
+ return false;
+
+ auto &After = GetLookAheadToken(2);
+ if (!After.isOneOf(tok::semi, tok::comma) &&
+ !(AllowDefinition &&
+ After.isOneOf(tok::l_brace, tok::colon, tok::kw_try)))
+ return false;
+
+ EqualLoc = ConsumeToken();
+ PureSpecLoc = ConsumeToken();
+ return true;
+ };
SmallVector<Decl *, 8> DeclsInGroup;
ExprResult BitfieldSize;
bool ExpectSemi = true;
// Parse the first declarator.
- ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
- LateParsedAttrs);
-
- // If this has neither a name nor a bit width, something has gone seriously
- // wrong. Skip until the semi-colon or }.
- if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ if (ParseCXXMemberDeclaratorBeforeInitializer(
+ DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {
TryConsumeToken(tok::semi);
return;
}
@@ -2314,16 +2411,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (BitfieldSize.isUnset()) {
// MSVC permits pure specifier on inline functions defined at class scope.
// Hence check for =0 before checking for function definition.
- if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) &&
- DeclaratorInfo.isFunctionDeclarator() &&
- NextToken().is(tok::numeric_constant)) {
- EqualLoc = ConsumeToken();
- Init = ParseInitializer();
- if (Init.isInvalid())
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- else
- HasInitializer = true;
- }
+ if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction())
+ TryConsumePureSpecifier(/*AllowDefinition*/ true);
FunctionDefinitionKind DefinitionKind = FDK_Declaration;
// function-definition:
@@ -2334,7 +2423,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) {
DefinitionKind = FDK_Definition;
} else if (DeclaratorInfo.isFunctionDeclarator()) {
- if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
+ if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) {
DefinitionKind = FDK_Definition;
} else if (Tok.is(tok::equal)) {
const Token &KW = NextToken();
@@ -2344,6 +2433,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DefinitionKind = FDK_Deleted;
}
}
+ DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);
// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
@@ -2354,7 +2444,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ProhibitAttributes(FnAttrs);
}
- if (DefinitionKind) {
+ if (DefinitionKind != FDK_Declaration) {
if (!DeclaratorInfo.isFunctionDeclarator()) {
Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);
ConsumeBrace();
@@ -2376,7 +2466,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Decl *FunDecl =
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
- VS, DefinitionKind, Init);
+ VS, PureSpecLoc);
if (FunDecl) {
for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
@@ -2402,16 +2492,25 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
while (1) {
InClassInitStyle HasInClassInit = ICIS_NoInit;
- if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
+ bool HasStaticInitializer = false;
+ if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) {
if (BitfieldSize.get()) {
Diag(Tok, diag::err_bitfield_member_init);
SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+ } else if (DeclaratorInfo.isDeclarationOfFunction()) {
+ // It's a pure-specifier.
+ if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))
+ // Parse it as an expression so that Sema can diagnose it.
+ HasStaticInitializer = true;
+ } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
+ DeclSpec::SCS_static &&
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
+ DeclSpec::SCS_typedef &&
+ !DS.isFriendSpecified()) {
+ // It's a default member initializer.
+ HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
} else {
- HasInitializer = true;
- if (!DeclaratorInfo.isDeclarationOfFunction() &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_typedef)
- HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
+ HasStaticInitializer = true;
}
}
@@ -2451,10 +2550,20 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);
}
- // Handle the initializer.
+ // Error recovery might have converted a non-static member into a static
+ // member.
if (HasInClassInit != ICIS_NoInit &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
- DeclSpec::SCS_static) {
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec() ==
+ DeclSpec::SCS_static) {
+ HasInClassInit = ICIS_NoInit;
+ HasStaticInitializer = true;
+ }
+
+ if (ThisDecl && PureSpecLoc.isValid())
+ Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc);
+
+ // Handle the initializer.
+ if (HasInClassInit != ICIS_NoInit) {
// The initializer was deferred; parse it and cache the tokens.
Diag(Tok, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_nonstatic_member_init
@@ -2474,11 +2583,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ThisDecl->setInvalidDecl();
} else
ParseCXXNonStaticMemberInitializer(ThisDecl);
- } else if (HasInitializer) {
+ } else if (HasStaticInitializer) {
// Normal initializer.
- if (!Init.isUsable())
- Init = ParseCXXMemberInitializer(
- ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
+ ExprResult Init = ParseCXXMemberInitializer(
+ ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
if (Init.isInvalid())
SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
@@ -2530,16 +2638,16 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Parse the next declarator.
DeclaratorInfo.clear();
VS.clear();
- BitfieldSize = true;
- Init = true;
- HasInitializer = false;
+ BitfieldSize = ExprResult(/*Invalid=*/false);
+ EqualLoc = PureSpecLoc = SourceLocation();
DeclaratorInfo.setCommaLoc(CommaLoc);
// GNU attributes are allowed before the second and subsequent declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
- ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
- LateParsedAttrs);
+ if (ParseCXXMemberDeclaratorBeforeInitializer(
+ DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))
+ break;
}
if (ExpectSemi &&
@@ -2554,13 +2662,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
}
-/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or
-/// pure-specifier. Also detect and reject any attempted defaulted/deleted
-/// function definition. The location of the '=', if any, will be placed in
-/// EqualLoc.
+/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer.
+/// Also detect and reject any attempted defaulted/deleted function definition.
+/// The location of the '=', if any, will be placed in EqualLoc.
///
-/// pure-specifier:
-/// '= 0'
+/// This does not check for a pure-specifier; that's handled elsewhere.
///
/// brace-or-equal-initializer:
/// '=' initializer-expression
@@ -2578,7 +2684,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
/// be a constant-expression.
ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
SourceLocation &EqualLoc) {
- assert((Tok.is(tok::equal) || Tok.is(tok::l_brace))
+ assert(Tok.isOneOf(tok::equal, tok::l_brace)
&& "Data member initializer not starting with '=' or '{'");
EnterExpressionEvaluationContext Context(Actions,
@@ -2592,8 +2698,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
// An initializer of '= delete p, foo' will never be parsed, because
// a top-level comma always ends the initializer expression.
const Token &Next = NextToken();
- if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
- Next.is(tok::eof)) {
+ if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) {
if (IsFunction)
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
<< 1 /* delete */;
@@ -2617,6 +2722,61 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
return ParseInitializer();
}
+void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
+ SourceLocation AttrFixitLoc,
+ unsigned TagType, Decl *TagDecl) {
+ // Skip the optional 'final' keyword.
+ if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
+ assert(isCXX11FinalKeyword() && "not a class definition");
+ ConsumeToken();
+
+ // Diagnose any C++11 attributes after 'final' keyword.
+ // We deliberately discard these attributes.
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
+
+ // This can only happen if we had malformed misplaced attributes;
+ // we only get called if there is a colon or left-brace after the
+ // attributes.
+ if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace))
+ return;
+ }
+
+ // Skip the base clauses. This requires actually parsing them, because
+ // otherwise we can't be sure where they end (a left brace may appear
+ // within a template argument).
+ if (Tok.is(tok::colon)) {
+ // Enter the scope of the class so that we can correctly parse its bases.
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
+ ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
+ TagType == DeclSpec::TST_interface);
+ auto OldContext =
+ Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
+
+ // Parse the bases but don't attach them to the class.
+ ParseBaseClause(nullptr);
+
+ Actions.ActOnTagFinishSkippedDefinition(OldContext);
+
+ if (!Tok.is(tok::l_brace)) {
+ Diag(PP.getLocForEndOfToken(PrevTokLocation),
+ diag::err_expected_lbrace_after_base_specifiers);
+ return;
+ }
+ }
+
+ // Skip the body.
+ assert(Tok.is(tok::l_brace));
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
+ T.skipToEnd();
+
+ // Parse and discard any trailing attributes.
+ ParsedAttributes Attrs(AttrFactory);
+ if (Tok.is(tok::kw___attribute))
+ MaybeParseGNUAttributes(Attrs);
+}
+
/// ParseCXXMemberSpecification - Parse the class definition.
///
/// member-specification:
@@ -2655,16 +2815,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
break;
}
- if ((S->getFlags() & Scope::FnScope)) {
- // If we're in a function or function template declared in the
- // body of a class, then this is a local class rather than a
- // nested class.
- const Scope *Parent = S->getParent();
- if (Parent->isTemplateParamScope())
- Parent = Parent->getParent();
- if (Parent->isClassScope())
- break;
- }
+ if ((S->getFlags() & Scope::FnScope))
+ // If we're in a function or function template then this is a local
+ // class rather than a nested class.
+ break;
}
}
@@ -2787,8 +2941,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one member-declaration.
- if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
- Tok.is(tok::kw___if_not_exists))) {
+ if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists,
+ tok::kw___if_not_exists)) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
continue;
}
@@ -2911,6 +3065,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
ParseLexedMemberInitializers(getCurrentClass());
ParseLexedMethodDefs(getCurrentClass());
PrevTokLocation = SavedPrevTokLocation;
+
+ // We've finished parsing everything, including default argument
+ // initializers.
+ Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl);
}
if (TagDecl)
@@ -2965,9 +3123,11 @@ void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {
/// mem-initializer ...[opt]
/// mem-initializer ...[opt] , mem-initializer-list
void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
- assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
+ assert(Tok.is(tok::colon) &&
+ "Constructor initializer always starts with ':'");
- // Poison the SEH identifiers so they are flagged as illegal in constructor initializers
+ // Poison the SEH identifiers so they are flagged as illegal in constructor
+ // initializers.
PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
SourceLocation ColonLoc = ConsumeToken();
@@ -2993,7 +3153,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
break;
// If the next token looks like a base or member initializer, assume that
// we're just missing a comma.
- else if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
+ else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) {
SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
Diag(Loc, diag::err_ctor_init_missing_comma)
<< FixItHint::CreateInsertion(Loc, ", ");
@@ -3184,13 +3344,16 @@ Parser::tryParseExceptionSpecification(bool Delayed,
T.consumeOpen();
NoexceptType = EST_ComputedNoexcept;
NoexceptExpr = ParseConstantExpression();
+ T.consumeClose();
// The argument must be contextually convertible to bool. We use
// ActOnBooleanCondition for this purpose.
- if (!NoexceptExpr.isInvalid())
+ if (!NoexceptExpr.isInvalid()) {
NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc,
NoexceptExpr.get());
- T.consumeClose();
- NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
+ NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
+ } else {
+ NoexceptType = EST_None;
+ }
} else {
// There is no argument.
NoexceptType = EST_BasicNoexcept;
@@ -3396,7 +3559,9 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
// Alternative tokens do not have identifier info, but their spelling
// starts with an alphabetical character.
SmallString<8> SpellingBuf;
- StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf);
+ SourceLocation SpellingLoc =
+ PP.getSourceManager().getSpellingLoc(Tok.getLocation());
+ StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);
if (isLetter(Spelling[0])) {
Loc = ConsumeToken();
return &PP.getIdentifierTable().get(Spelling);
@@ -3474,7 +3639,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
// The attribute was allowed to have arguments, but none were provided
// even though the attribute parsed successfully. This is an error.
Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
- return false;
} else if (!Attr->getMaxArgs()) {
// The attribute parsed successfully, but was not allowed to have any
// arguments. It doesn't matter whether any were provided -- the
@@ -3482,7 +3646,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
<< AttrName
<< FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
- return false;
}
}
}
@@ -3645,7 +3808,7 @@ SourceLocation Parser::SkipCXX11Attributes() {
return EndLoc;
}
-/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
+/// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr]
///
/// [MS] ms-attribute:
/// '[' token-seq ']'
@@ -3657,13 +3820,15 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc) {
assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
- while (Tok.is(tok::l_square)) {
+ do {
// FIXME: If this is actually a C++11 attribute, parse it as one.
- ConsumeBracket();
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
- if (endLoc) *endLoc = Tok.getLocation();
- ExpectAndConsume(tok::r_square);
- }
+ T.consumeClose();
+ if (endLoc)
+ *endLoc = T.getCloseLocation();
+ } while (Tok.is(tok::l_square));
}
void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
@@ -3695,7 +3860,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// __if_exists, __if_not_exists can nest.
- if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
+ if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
continue;
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index d0d97de..b866798 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -205,6 +205,24 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
return Actions.ActOnConstantExpression(Res);
}
+/// \brief Parse a constraint-expression.
+///
+/// \verbatim
+/// constraint-expression: [Concepts TS temp.constr.decl p1]
+/// logical-or-expression
+/// \endverbatim
+ExprResult Parser::ParseConstraintExpression() {
+ // FIXME: this may erroneously consume a function-body as the braced
+ // initializer list of a compound literal
+ //
+ // FIXME: this may erroneously consume a parenthesized rvalue reference
+ // declarator as a parenthesized address-of-label expression
+ ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));
+ ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
+
+ return Res;
+}
+
bool Parser::isNotExpressionStart() {
tok::TokenKind K = Tok.getKind();
if (K == tok::l_brace || K == tok::r_brace ||
@@ -347,7 +365,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHS = ParseCastExpression(false);
if (RHS.isInvalid()) {
+ // FIXME: Errors generated by the delayed typo correction should be
+ // printed before errors from parsing the RHS, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
+ if (TernaryMiddle.isUsable())
+ TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@@ -380,7 +402,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHSIsInitList = false;
if (RHS.isInvalid()) {
+ // FIXME: Errors generated by the delayed typo correction should be
+ // printed before errors from ParseRHSOfBinaryExpression, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
+ if (TernaryMiddle.isUsable())
+ TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@@ -446,8 +472,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
namespace {
class CastExpressionIdValidator : public CorrectionCandidateCallback {
public:
- CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes)
- : AllowNonTypes(AllowNonTypes) {
+ CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
+ : NextToken(Next), AllowNonTypes(AllowNonTypes) {
WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
}
@@ -458,11 +484,23 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
if (isa<TypeDecl>(ND))
return WantTypeSpecifiers;
- return AllowNonTypes &&
- CorrectionCandidateCallback::ValidateCandidate(candidate);
+
+ if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))
+ return false;
+
+ if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period))
+ return true;
+
+ for (auto *C : candidate) {
+ NamedDecl *ND = C->getUnderlyingDecl();
+ if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))
+ return true;
+ }
+ return false;
}
private:
+ Token NextToken;
bool AllowNonTypes;
};
}
@@ -808,11 +846,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
}
- if (Next.is(tok::coloncolon) ||
- (!ColonIsSacred && Next.is(tok::colon)) ||
- Next.is(tok::less) ||
- Next.is(tok::l_paren) ||
- Next.is(tok::l_brace)) {
+ if ((!ColonIsSacred && Next.is(tok::colon)) ||
+ Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,
+ tok::l_brace)) {
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
if (TryAnnotateTypeOrScopeToken())
return ExprError();
@@ -908,14 +944,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation TemplateKWLoc;
Token Replacement;
auto Validator = llvm::make_unique<CastExpressionIdValidator>(
- isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
+ Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
Validator->IsAddressOfOperand = isAddressOfOperand;
- Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
+ if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
+ Validator->WantExpressionKeywords = false;
+ Validator->WantRemainingKeywords = false;
+ } else {
+ Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
+ }
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(
getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
isAddressOfOperand, std::move(Validator),
- /*IsInlineAsmIdentifier=*/false, &Replacement);
+ /*IsInlineAsmIdentifier=*/false,
+ Tok.is(tok::r_paren) ? nullptr : &Replacement);
if (!Res.isInvalid() && !Res.get()) {
UnconsumeToken(Replacement);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
@@ -1018,6 +1060,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
// unary-expression: 'sizeof' '(' type-name ')'
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
+ // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
+ case tok::kw___builtin_omp_required_simd_align:
return ParseUnaryExprOrTypeTraitExpression();
case tok::ampamp: { // unary-expression: '&&' identifier
SourceLocation AmpAmpLoc = ConsumeToken();
@@ -1441,10 +1485,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
- LHS.get())) {
+ if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
+ Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+ })) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
+ } else if (LHS.isInvalid()) {
+ for (auto &E : ArgExprs)
+ Actions.CorrectDelayedTyposInExpr(E);
}
}
}
@@ -1453,7 +1501,19 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
} else if (Tok.isNot(tok::r_paren)) {
- PT.consumeClose();
+ bool HadDelayedTypo = false;
+ if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get())
+ HadDelayedTypo = true;
+ for (auto &E : ArgExprs)
+ if (Actions.CorrectDelayedTyposInExpr(E).get() != E)
+ HadDelayedTypo = true;
+ // If there were delayed typos in the LHS or ArgExprs, call SkipUntil
+ // instead of PT.consumeClose() to avoid emitting extra diagnostics for
+ // the unmatched l_paren.
+ if (HadDelayedTypo)
+ SkipUntil(tok::r_paren, StopAtSemi);
+ else
+ PT.consumeClose();
LHS = ExprError();
} else {
assert((ArgExprs.size() == 0 ||
@@ -1510,14 +1570,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
cutOffParsing();
return ExprError();
}
-
+
if (MayBePseudoDestructor && !LHS.isInvalid()) {
LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
ObjectType);
break;
}
- // Either the action has told is that this cannot be a
+ // Either the action has told us that this cannot be a
// pseudo-destructor expression (based on the type of base
// expression), or we didn't see a '~' in the right place. We
// can still parse a destructor name here, but in that case it
@@ -1526,7 +1586,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// FIXME: Add support for explicit call of template constructor.
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
- if (getLangOpts().ObjC2 && OpKind == tok::period && Tok.is(tok::kw_class)) {
+ if (getLangOpts().ObjC2 && OpKind == tok::period &&
+ Tok.is(tok::kw_class)) {
// Objective-C++:
// After a '.' in a member access expression, treat the keyword
// 'class' as if it were an identifier.
@@ -1551,8 +1612,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
- : nullptr,
- Tok.is(tok::l_paren));
+ : nullptr);
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
@@ -1596,10 +1656,10 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
ParsedType &CastTy,
SourceRange &CastRange) {
- assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
- OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) ||
- OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) &&
- "Not a typeof/sizeof/alignof/vec_step expression!");
+ assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
+ tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
+ tok::kw___builtin_omp_required_simd_align) &&
+ "Not a typeof/sizeof/alignof/vec_step expression!");
ExprResult Operand;
@@ -1607,8 +1667,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (Tok.isNot(tok::l_paren)) {
// If construct allows a form without parenthesis, user may forget to put
// pathenthesis around type name.
- if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) ||
- OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) {
+ if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
+ tok::kw__Alignof)) {
if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
@@ -1682,9 +1742,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
/// [C++11] 'alignof' '(' type-id ')'
/// \endverbatim
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
- assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) ||
- Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) ||
- Tok.is(tok::kw_vec_step)) &&
+ assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
+ tok::kw__Alignof, tok::kw_vec_step,
+ tok::kw___builtin_omp_required_simd_align) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
ConsumeToken();
@@ -1735,7 +1795,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
RParenLoc);
}
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
@@ -1750,11 +1810,12 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) ||
- OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof))
ExprKind = UETT_AlignOf;
else if (OpTok.is(tok::kw_vec_step))
ExprKind = UETT_VecStep;
+ else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
+ ExprKind = UETT_OpenMPRequiredSimdAlign;
if (isCastExpr)
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
@@ -1763,7 +1824,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastTy.getAsOpaquePtr(),
CastRange);
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo();
// If we get here, the operand to the sizeof/alignof was an expresion.
@@ -2064,10 +2125,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Diagnose use of bridge casts in non-arc mode.
bool BridgeCast = (getLangOpts().ObjC2 &&
- (Tok.is(tok::kw___bridge) ||
- Tok.is(tok::kw___bridge_transfer) ||
- Tok.is(tok::kw___bridge_retained) ||
- Tok.is(tok::kw___bridge_retain)));
+ Tok.isOneOf(tok::kw___bridge,
+ tok::kw___bridge_transfer,
+ tok::kw___bridge_retained,
+ tok::kw___bridge_retain));
if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
if (!TryConsumeToken(tok::kw___bridge)) {
StringRef BridgeCastName = Tok.getName();
@@ -2088,6 +2149,17 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) {
Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope));
} else {
+ // Find the nearest non-record decl context. Variables declared in a
+ // statement expression behave as if they were declared in the enclosing
+ // function, block, or other code construct.
+ DeclContext *CodeDC = Actions.CurContext;
+ while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) {
+ CodeDC = CodeDC->getParent();
+ assert(CodeDC && !CodeDC->isFileContext() &&
+ "statement expr not in code context");
+ }
+ Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false);
+
Actions.ActOnStartStmtExpr();
StmtResult Stmt(ParseCompoundStatement(true));
@@ -2256,6 +2328,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
InMessageExpressionRAIIObject InMessage(*this, false);
Result = ParseExpression(MaybeTypeCast);
+ if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) {
+ // Correct typos in non-C++ code earlier so that implicit-cast-like
+ // expressions are parsed correctly.
+ Result = Actions.CorrectDelayedTyposInExpr(Result);
+ }
ExprType = SimpleExpr;
if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
@@ -2354,7 +2431,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// C11 6.5.1.1p3 "The controlling expression of a generic selection is
// not evaluated."
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
- ControllingExpr = ParseAssignmentExpression();
+ ControllingExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (ControllingExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@@ -2400,7 +2478,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// FIXME: These expressions should be parsed in a potentially potentially
// evaluated context.
- ExprResult ER(ParseAssignmentExpression());
+ ExprResult ER(
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
if (ER.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@@ -2493,17 +2572,14 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS,
/// [C++0x] assignment-expression
/// [C++0x] braced-init-list
/// \endverbatim
-bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
+bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
SmallVectorImpl<SourceLocation> &CommaLocs,
- void (Sema::*Completer)(Scope *S,
- Expr *Data,
- ArrayRef<Expr *> Args),
- Expr *Data) {
+ std::function<void()> Completer) {
bool SawError = false;
while (1) {
if (Tok.is(tok::code_completion)) {
if (Completer)
- (Actions.*Completer)(getCurScope(), Data, Exprs);
+ Completer();
else
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
cutOffParsing();
@@ -2588,9 +2664,6 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
ParseDeclarator(DeclaratorInfo);
- // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
- DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation());
-
MaybeParseGNUAttributes(DeclaratorInfo);
// Inform sema that we are starting a block.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index 67496ed..c1dafe9 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -118,6 +118,7 @@ void Parser::CheckForLParenAfterColonColon() {
// Eat the '('.
ConsumeParen();
Token RParen;
+ RParen.setLocation(SourceLocation());
// Do we have a ')' ?
NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1);
if (NextTok.is(tok::r_paren)) {
@@ -194,6 +195,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Tok.is(tok::annot_cxxscope)) {
assert(!LastII && "want last identifier but have already annotated scope");
+ assert(!MayBePseudoDestructor && "unexpected annot_cxxscope");
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
Tok.getAnnotationRange(),
SS);
@@ -208,6 +210,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SS = TemplateId->SS;
}
+ // Has to happen before any "return false"s in this function.
+ bool CheckForDestructor = false;
+ if (MayBePseudoDestructor && *MayBePseudoDestructor) {
+ CheckForDestructor = true;
+ *MayBePseudoDestructor = false;
+ }
+
if (LastII)
*LastII = nullptr;
@@ -244,14 +253,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS);
}
- bool CheckForDestructor = false;
- if (MayBePseudoDestructor && *MayBePseudoDestructor) {
- CheckForDestructor = true;
- *MayBePseudoDestructor = false;
- }
-
if (!HasScopeSpecifier &&
- (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) {
+ Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
@@ -484,7 +487,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// as the name in a nested-name-specifier.
Token Identifier = Tok;
SourceLocation IdLoc = ConsumeToken();
- assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
+ assert(Tok.isOneOf(tok::coloncolon, tok::colon) &&
"NextToken() not working properly!");
Token ColonColon = Tok;
SourceLocation CCLoc = ConsumeToken();
@@ -659,7 +662,8 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
Token Replacement;
- ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);
+ ExprResult Result =
+ tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);
if (Result.isUnset()) {
// If the ExprResult is valid but null, then typo correction suggested a
// keyword replacement that needs to be reparsed.
@@ -888,7 +892,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
Parens.getCloseLocation(),
Exprs);
}
- } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) {
+ } else if (Tok.isOneOf(tok::l_brace, tok::equal)) {
// Each lambda init-capture forms its own full expression, which clears
// Actions.MaybeODRUseExprs. So create an expression evaluation context
// to save the necessary state, and restore it later.
@@ -1090,6 +1094,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// compatible with GCC.
MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+ // MSVC-style attributes must be parsed before the mutable specifier to be
+ // compatible with MSVC.
+ MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc);
+
// Parse 'mutable'[opt].
SourceLocation MutableLoc;
if (TryConsumeToken(tok::kw_mutable, MutableLoc))
@@ -1151,8 +1159,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
- } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
- Tok.is(tok::kw___attribute) ||
+ } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute) ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
// It's common to forget that one needs '()' before 'mutable', an attribute
// specifier, or the result type. Deal with this.
@@ -1485,9 +1492,8 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
ParseDecltypeSpecifier(DS);
if (DS.getTypeSpecType() == TST_error)
return ExprError();
- return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc,
- OpKind, TildeLoc, DS,
- Tok.is(tok::l_paren));
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
+ TildeLoc, DS);
}
if (!Tok.is(tok::identifier)) {
@@ -1510,11 +1516,9 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
/*AssumeTemplateName=*/true))
return ExprError();
- return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base,
- OpLoc, OpKind,
- SS, FirstTypeName, CCLoc,
- TildeLoc, SecondTypeName,
- Tok.is(tok::l_paren));
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
+ SS, FirstTypeName, CCLoc, TildeLoc,
+ SecondTypeName);
}
/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
@@ -1602,7 +1606,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(Exprs, CommaLocs)) {
+ if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ Actions.CodeCompleteConstructor(getCurScope(),
+ TypeRep.get()->getCanonicalTypeInternal(),
+ DS.getLocEnd(), Exprs);
+ })) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1678,7 +1686,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
// type-specifier-seq
DeclSpec DS(AttrFactory);
DS.takeAttributesFrom(attrs);
- ParseSpecifierQualifierList(DS);
+ ParseSpecifierQualifierList(DS, AS_none, DSC_condition);
// declarator
Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
@@ -1797,13 +1805,6 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken();
- // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
- // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface. If we don't have Objective-C or a '<', this is
- // just a normal reference to a typedef name.
- if (Tok.is(tok::less) && getLangOpts().ObjC1)
- ParseObjCProtocolQualifiers(DS);
-
DS.Finish(Diags, PP, Policy);
return;
}
@@ -2509,14 +2510,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// If the user wrote ~T::T, correct it to T::~T.
+ DeclaratorScopeObj DeclScopeObj(*this, SS);
if (!TemplateSpecified && NextToken().is(tok::coloncolon)) {
+ // Don't let ParseOptionalCXXScopeSpecifier() "correct"
+ // `int A; struct { ~A::A(); };` to `int A; struct { ~A:A(); };`,
+ // it will confuse this recovery logic.
+ ColonProtectionRAIIObject ColonRAII(*this, false);
+
if (SS.isSet()) {
AnnotateScopeToken(SS, /*NewAnnotation*/true);
SS.clear();
}
if (ParseOptionalCXXScopeSpecifier(SS, ObjectType, EnteringContext))
return true;
- if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon)) {
+ if (SS.isNotEmpty())
+ ObjectType = ParsedType();
+ if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon) ||
+ !SS.isSet()) {
Diag(TildeLoc, diag::err_destructor_tilde_scope);
return true;
}
@@ -2525,6 +2535,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Diag(TildeLoc, diag::err_destructor_tilde_scope)
<< FixItHint::CreateRemoval(TildeLoc)
<< FixItHint::CreateInsertion(Tok.getLocation(), "~");
+
+ // Temporarily enter the scope for the rest of this function.
+ if (Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
+ DeclScopeObj.EnterDeclaratorScope();
}
// Parse the class-name (or template-name in a simple-template-id).
@@ -2668,7 +2682,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
ConstructorLParen = T.getOpenLocation();
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
- if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+ if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
+ ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
+ DeclaratorInfo).get();
+ Actions.CodeCompleteConstructor(getCurScope(),
+ TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getLocEnd(),
+ ConstructorArgs);
+ })) {
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
return ExprError();
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
index 7fe9862..4896ff0 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
@@ -148,7 +148,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
<< FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
- NewSyntax.str());
+ NewSyntax);
Designation D;
D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
@@ -252,26 +252,40 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// Three cases. This is a message send to a type: [type foo]
// This is a message send to super: [super foo]
// This is a message sent to an expr: [super.bar foo]
- switch (Sema::ObjCMessageKind Kind
- = Actions.getObjCMessageKind(getCurScope(), II, IILoc,
- II == Ident_super,
- NextToken().is(tok::period),
- ReceiverType)) {
+ switch (Actions.getObjCMessageKind(
+ getCurScope(), II, IILoc, II == Ident_super,
+ NextToken().is(tok::period), ReceiverType)) {
case Sema::ObjCSuperMessage:
+ CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ ConsumeToken(),
+ ParsedType(),
+ nullptr);
+
case Sema::ObjCClassMessage:
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
- if (Kind == Sema::ObjCSuperMessage)
- return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
- ConsumeToken(),
- ParsedType(),
- nullptr);
ConsumeToken(); // the identifier
if (!ReceiverType) {
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
}
- return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ // Parse type arguments and protocol qualifiers.
+ if (Tok.is(tok::less)) {
+ SourceLocation NewEndLoc;
+ TypeResult NewReceiverType
+ = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,
+ /*consumeLastToken=*/true,
+ NewEndLoc);
+ if (!NewReceiverType.isUsable()) {
+ SkipUntil(tok::r_square, StopAtSemi);
+ return ExprError();
+ }
+
+ ReceiverType = NewReceiverType.get();
+ }
+
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ReceiverType,
nullptr);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
index a597a16..ed60904 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
@@ -95,14 +96,17 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
///
/// objc-class-declaration:
-/// '@' 'class' identifier-list ';'
+/// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';'
+///
+/// objc-class-forward-decl:
+/// identifier objc-type-parameter-list[opt]
///
Parser::DeclGroupPtrTy
Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
SmallVector<IdentifierInfo *, 8> ClassNames;
SmallVector<SourceLocation, 8> ClassLocs;
-
+ SmallVector<ObjCTypeParamList *, 8> ClassTypeParams;
while (1) {
MaybeSkipAttributes(tok::objc_class);
@@ -115,6 +119,14 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
+ // Parse the optional objc-type-parameter-list.
+ ObjCTypeParamList *TypeParams = nullptr;
+ if (Tok.is(tok::less)) {
+ TypeParams = parseObjCTypeParamList();
+ if (TypeParams)
+ Actions.popObjCTypeParamList(getCurScope(), TypeParams);
+ }
+ ClassTypeParams.push_back(TypeParams);
if (!TryConsumeToken(tok::comma))
break;
}
@@ -125,6 +137,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
ClassLocs.data(),
+ ClassTypeParams,
ClassNames.size());
}
@@ -153,20 +166,20 @@ void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
/// objc-category-interface
///
/// objc-class-interface:
-/// '@' 'interface' identifier objc-superclass[opt]
-/// objc-protocol-refs[opt]
+/// '@' 'interface' identifier objc-type-parameter-list[opt]
+/// objc-superclass[opt] objc-protocol-refs[opt]
/// objc-class-instance-variables[opt]
/// objc-interface-decl-list
/// @end
///
/// objc-category-interface:
-/// '@' 'interface' identifier '(' identifier[opt] ')'
-/// objc-protocol-refs[opt]
+/// '@' 'interface' identifier objc-type-parameter-list[opt]
+/// '(' identifier[opt] ')' objc-protocol-refs[opt]
/// objc-interface-decl-list
/// @end
///
/// objc-superclass:
-/// ':' identifier
+/// ':' identifier objc-type-arguments[opt]
///
/// objc-class-interface-attributes:
/// __attribute__((visibility("default")))
@@ -201,7 +214,20 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
- if (Tok.is(tok::l_paren) &&
+
+ // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter
+ // case, LAngleLoc will be valid and ProtocolIdents will capture the
+ // protocol references (that have not yet been resolved).
+ SourceLocation LAngleLoc, EndProtoLoc;
+ SmallVector<IdentifierLocPair, 8> ProtocolIdents;
+ ObjCTypeParamList *typeParameterList = nullptr;
+ if (Tok.is(tok::less)) {
+ typeParameterList = parseObjCTypeParamListOrProtocolRefs(LAngleLoc,
+ ProtocolIdents,
+ EndProtoLoc);
+ }
+
+ if (Tok.is(tok::l_paren) &&
!isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -236,17 +262,19 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
}
// Next, we need to check for any protocol references.
- SourceLocation LAngleLoc, EndProtoLoc;
+ assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
SmallVector<Decl *, 8> ProtocolRefs;
SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
- LAngleLoc, EndProtoLoc))
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
+ LAngleLoc, EndProtoLoc,
+ /*consumeLastToken=*/true))
return nullptr;
Decl *CategoryType =
Actions.ActOnStartCategoryInterface(AtLoc,
nameId, nameLoc,
+ typeParameterList,
categoryId, categoryLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
@@ -257,12 +285,20 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
+
+ if (typeParameterList)
+ Actions.popObjCTypeParamList(getCurScope(), typeParameterList);
+
return CategoryType;
}
// Parse a class interface.
IdentifierInfo *superClassId = nullptr;
SourceLocation superClassLoc;
-
+ SourceLocation typeArgsLAngleLoc;
+ SmallVector<ParsedType, 4> typeArgs;
+ SourceLocation typeArgsRAngleLoc;
+ SmallVector<Decl *, 4> protocols;
+ SmallVector<SourceLocation, 4> protocolLocs;
if (Tok.is(tok::colon)) { // a super class is specified.
ConsumeToken();
@@ -280,33 +316,295 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
}
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken();
+
+ // Type arguments for the superclass or protocol conformances.
+ if (Tok.is(tok::less)) {
+ parseObjCTypeArgsOrProtocolQualifiers(ParsedType(),
+ typeArgsLAngleLoc,
+ typeArgs,
+ typeArgsRAngleLoc,
+ LAngleLoc,
+ protocols,
+ protocolLocs,
+ EndProtoLoc,
+ /*consumeLastToken=*/true,
+ /*warnOnIncompleteProtocols=*/true);
+ }
}
+
// Next, we need to check for any protocol references.
- SmallVector<Decl *, 8> ProtocolRefs;
- SmallVector<SourceLocation, 8> ProtocolLocs;
- SourceLocation LAngleLoc, EndProtoLoc;
- if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
- LAngleLoc, EndProtoLoc))
+ if (LAngleLoc.isValid()) {
+ if (!ProtocolIdents.empty()) {
+ // We already parsed the protocols named when we thought we had a
+ // type parameter list. Translate them into actual protocol references.
+ for (const auto &pair : ProtocolIdents) {
+ protocolLocs.push_back(pair.second);
+ }
+ Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true,
+ /*ForObjCContainer=*/true,
+ &ProtocolIdents[0], ProtocolIdents.size(),
+ protocols);
+ }
+ } else if (protocols.empty() && Tok.is(tok::less) &&
+ ParseObjCProtocolReferences(protocols, protocolLocs, true, true,
+ LAngleLoc, EndProtoLoc,
+ /*consumeLastToken=*/true)) {
return nullptr;
+ }
if (Tok.isNot(tok::less))
- Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
+ Actions.ActOnTypedefedProtocols(protocols, superClassId, superClassLoc);
Decl *ClsType =
- Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc,
- superClassId, superClassLoc,
- ProtocolRefs.data(), ProtocolRefs.size(),
- ProtocolLocs.data(),
+ Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc,
+ typeParameterList, superClassId,
+ superClassLoc,
+ typeArgs,
+ SourceRange(typeArgsLAngleLoc,
+ typeArgsRAngleLoc),
+ protocols.data(), protocols.size(),
+ protocolLocs.data(),
EndProtoLoc, attrs.getList());
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
+
+ if (typeParameterList)
+ Actions.popObjCTypeParamList(getCurScope(), typeParameterList);
+
return ClsType;
}
+/// Add an attribute for a context-sensitive type nullability to the given
+/// declarator.
+static void addContextSensitiveTypeNullability(Parser &P,
+ Declarator &D,
+ NullabilityKind nullability,
+ SourceLocation nullabilityLoc,
+ bool &addedToDeclSpec) {
+ // Create the attribute.
+ auto getNullabilityAttr = [&]() -> AttributeList * {
+ return D.getAttributePool().create(
+ P.getNullabilityKeyword(nullability),
+ SourceRange(nullabilityLoc),
+ nullptr, SourceLocation(),
+ nullptr, 0,
+ AttributeList::AS_ContextSensitiveKeyword);
+ };
+
+ if (D.getNumTypeObjects() > 0) {
+ // Add the attribute to the declarator chunk nearest the declarator.
+ auto nullabilityAttr = getNullabilityAttr();
+ DeclaratorChunk &chunk = D.getTypeObject(0);
+ nullabilityAttr->setNext(chunk.getAttrListRef());
+ chunk.getAttrListRef() = nullabilityAttr;
+ } else if (!addedToDeclSpec) {
+ // Otherwise, just put it on the declaration specifiers (if one
+ // isn't there already).
+ D.getMutableDeclSpec().addAttributes(getNullabilityAttr());
+ addedToDeclSpec = true;
+ }
+}
+
+/// Parse an Objective-C type parameter list, if present, or capture
+/// the locations of the protocol identifiers for a list of protocol
+/// references.
+///
+/// objc-type-parameter-list:
+/// '<' objc-type-parameter (',' objc-type-parameter)* '>'
+///
+/// objc-type-parameter:
+/// objc-type-parameter-variance? identifier objc-type-parameter-bound[opt]
+///
+/// objc-type-parameter-bound:
+/// ':' type-name
+///
+/// objc-type-parameter-variance:
+/// '__covariant'
+/// '__contravariant'
+///
+/// \param lAngleLoc The location of the starting '<'.
+///
+/// \param protocolIdents Will capture the list of identifiers, if the
+/// angle brackets contain a list of protocol references rather than a
+/// type parameter list.
+///
+/// \param rAngleLoc The location of the ending '>'.
+ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
+ SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc,
+ bool mayBeProtocolList) {
+ assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");
+
+ // Within the type parameter list, don't treat '>' as an operator.
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+
+ // Local function to "flush" the protocol identifiers, turning them into
+ // type parameters.
+ SmallVector<Decl *, 4> typeParams;
+ auto makeProtocolIdentsIntoTypeParameters = [&]() {
+ unsigned index = 0;
+ for (const auto &pair : protocolIdents) {
+ DeclResult typeParam = Actions.actOnObjCTypeParam(
+ getCurScope(),
+ ObjCTypeParamVariance::Invariant,
+ SourceLocation(),
+ index++,
+ pair.first,
+ pair.second,
+ SourceLocation(),
+ ParsedType());
+ if (typeParam.isUsable())
+ typeParams.push_back(typeParam.get());
+ }
+
+ protocolIdents.clear();
+ mayBeProtocolList = false;
+ };
+
+ bool invalid = false;
+ lAngleLoc = ConsumeToken();
+
+ do {
+ // Parse the variance, if any.
+ SourceLocation varianceLoc;
+ ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant;
+ if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) {
+ variance = Tok.is(tok::kw___covariant)
+ ? ObjCTypeParamVariance::Covariant
+ : ObjCTypeParamVariance::Contravariant;
+ varianceLoc = ConsumeToken();
+
+ // Once we've seen a variance specific , we know this is not a
+ // list of protocol references.
+ if (mayBeProtocolList) {
+ // Up until now, we have been queuing up parameters because they
+ // might be protocol references. Turn them into parameters now.
+ makeProtocolIdentsIntoTypeParameters();
+ }
+ }
+
+ // Parse the identifier.
+ if (!Tok.is(tok::identifier)) {
+ // Code completion.
+ if (Tok.is(tok::code_completion)) {
+ // FIXME: If these aren't protocol references, we'll need different
+ // completions.
+ Actions.CodeCompleteObjCProtocolReferences(protocolIdents.data(),
+ protocolIdents.size());
+ cutOffParsing();
+
+ // FIXME: Better recovery here?.
+ return nullptr;
+ }
+
+ Diag(Tok, diag::err_objc_expected_type_parameter);
+ invalid = true;
+ break;
+ }
+
+ IdentifierInfo *paramName = Tok.getIdentifierInfo();
+ SourceLocation paramLoc = ConsumeToken();
+
+ // If there is a bound, parse it.
+ SourceLocation colonLoc;
+ TypeResult boundType;
+ if (TryConsumeToken(tok::colon, colonLoc)) {
+ // Once we've seen a bound, we know this is not a list of protocol
+ // references.
+ if (mayBeProtocolList) {
+ // Up until now, we have been queuing up parameters because they
+ // might be protocol references. Turn them into parameters now.
+ makeProtocolIdentsIntoTypeParameters();
+ }
+
+ // type-name
+ boundType = ParseTypeName();
+ if (boundType.isInvalid())
+ invalid = true;
+ } else if (mayBeProtocolList) {
+ // If this could still be a protocol list, just capture the identifier.
+ // We don't want to turn it into a parameter.
+ protocolIdents.push_back(std::make_pair(paramName, paramLoc));
+ continue;
+ }
+
+ // Create the type parameter.
+ DeclResult typeParam = Actions.actOnObjCTypeParam(getCurScope(),
+ variance,
+ varianceLoc,
+ typeParams.size(),
+ paramName,
+ paramLoc,
+ colonLoc,
+ boundType.isUsable()
+ ? boundType.get()
+ : ParsedType());
+ if (typeParam.isUsable())
+ typeParams.push_back(typeParam.get());
+ } while (TryConsumeToken(tok::comma));
+
+ // Parse the '>'.
+ if (invalid) {
+ SkipUntil(tok::greater, tok::at, StopBeforeMatch);
+ if (Tok.is(tok::greater))
+ ConsumeToken();
+ } else if (ParseGreaterThanInTemplateList(rAngleLoc,
+ /*ConsumeLastToken=*/true,
+ /*ObjCGenericList=*/true)) {
+ Diag(lAngleLoc, diag::note_matching) << "'<'";
+ SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus,
+ tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace,
+ tok::comma, tok::semi },
+ StopBeforeMatch);
+ if (Tok.is(tok::greater))
+ ConsumeToken();
+ }
+
+ if (mayBeProtocolList) {
+ // A type parameter list must be followed by either a ':' (indicating the
+ // presence of a superclass) or a '(' (indicating that this is a category
+ // or extension). This disambiguates between an objc-type-parameter-list
+ // and a objc-protocol-refs.
+ if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) {
+ // Returning null indicates that we don't have a type parameter list.
+ // The results the caller needs to handle the protocol references are
+ // captured in the reference parameters already.
+ return nullptr;
+ }
+
+ // We have a type parameter list that looks like a list of protocol
+ // references. Turn that parameter list into type parameters.
+ makeProtocolIdentsIntoTypeParameters();
+ }
+
+ // Form the type parameter list.
+ ObjCTypeParamList *list = Actions.actOnObjCTypeParamList(
+ getCurScope(),
+ lAngleLoc,
+ typeParams,
+ rAngleLoc);
+
+ // Clear out the angle locations; they're used by the caller to indicate
+ // whether there are any protocol references.
+ lAngleLoc = SourceLocation();
+ rAngleLoc = SourceLocation();
+ return list;
+}
+
+/// Parse an objc-type-parameter-list.
+ObjCTypeParamList *Parser::parseObjCTypeParamList() {
+ SourceLocation lAngleLoc;
+ SmallVector<IdentifierLocPair, 1> protocolIdents;
+ SourceLocation rAngleLoc;
+ return parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents,
+ rAngleLoc,
+ /*mayBeProtocolList=*/false);
+}
+
/// objc-interface-decl-list:
/// empty
/// objc-interface-decl-list objc-property-decl [OBJC2]
@@ -330,7 +628,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
while (1) {
// If this is a method prototype, parse it.
- if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
+ if (Tok.isOneOf(tok::minus, tok::plus)) {
if (Decl *methodPrototype =
ParseObjCMethodPrototype(MethodImplKind, false))
allMethods.push_back(methodPrototype);
@@ -445,6 +743,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
ParseObjCPropertyAttribute(OCDS);
}
+ bool addedToDeclSpec = false;
auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
if (FD.D.getIdentifier() == nullptr) {
Diag(AtLoc, diag::err_objc_property_requires_field_name)
@@ -457,6 +756,13 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
return;
}
+ // Map a nullability property attribute to a context-sensitive keyword
+ // attribute.
+ if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),
+ OCDS.getNullabilityLoc(),
+ addedToDeclSpec);
+
// Install the property declarator into interfaceDecl.
IdentifierInfo *SelName =
OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
@@ -510,6 +816,24 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
}
+/// Diagnose redundant or conflicting nullability information.
+static void diagnoseRedundantPropertyNullability(Parser &P,
+ ObjCDeclSpec &DS,
+ NullabilityKind nullability,
+ SourceLocation nullabilityLoc){
+ if (DS.getNullability() == nullability) {
+ P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
+ << DiagNullabilityKind(nullability, true)
+ << SourceRange(DS.getNullabilityLoc());
+ return;
+ }
+
+ P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ << DiagNullabilityKind(nullability, true)
+ << DiagNullabilityKind(DS.getNullability(), true)
+ << SourceRange(DS.getNullabilityLoc());
+}
+
/// Parse property attribute declarations.
///
/// property-attr-decl: '(' property-attrlist ')'
@@ -529,6 +853,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
/// strong
/// weak
/// unsafe_unretained
+/// nonnull
+/// nullable
+/// null_unspecified
+/// null_resettable
///
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
assert(Tok.getKind() == tok::l_paren);
@@ -614,6 +942,37 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
DS.setGetterName(SelIdent);
}
+ } else if (II->isStr("nonnull")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::NonNull,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);
+ } else if (II->isStr("nullable")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Nullable,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);
+ } else if (II->isStr("null_unspecified")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Unspecified,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
+ } else if (II->isStr("null_resettable")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Unspecified,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
+
+ // Also set the null_resettable bit.
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable);
} else {
Diag(AttrName, diag::err_objc_expected_property_attr) << II;
SkipUntil(tok::r_paren, StopAtSemi);
@@ -641,7 +1000,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
///
Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
bool MethodDefinition) {
- assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
+ assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");
tok::TokenKind methodType = Tok.getKind();
SourceLocation mLoc = ConsumeToken();
@@ -779,6 +1138,17 @@ bool Parser::isTokIdentifier_in() const {
/// objc-type-qualifier
/// objc-type-qualifiers objc-type-qualifier
///
+/// objc-type-qualifier:
+/// 'in'
+/// 'out'
+/// 'inout'
+/// 'oneway'
+/// 'bycopy'
+/// 'byref'
+/// 'nonnull'
+/// 'nullable'
+/// 'null_unspecified'
+///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
Declarator::TheContext Context) {
assert(Context == Declarator::ObjCParameterContext ||
@@ -796,10 +1166,13 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
const IdentifierInfo *II = Tok.getIdentifierInfo();
for (unsigned i = 0; i != objc_NumQuals; ++i) {
- if (II != ObjCTypeQuals[i])
+ if (II != ObjCTypeQuals[i] ||
+ NextToken().is(tok::less) ||
+ NextToken().is(tok::coloncolon))
continue;
ObjCDeclSpec::ObjCDeclQualifier Qual;
+ NullabilityKind Nullability;
switch (i) {
default: llvm_unreachable("Unknown decl qualifier");
case objc_in: Qual = ObjCDeclSpec::DQ_In; break;
@@ -808,8 +1181,28 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break;
+
+ case objc_nonnull:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::NonNull;
+ break;
+
+ case objc_nullable:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::Nullable;
+ break;
+
+ case objc_null_unspecified:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::Unspecified;
+ break;
}
+
+ // FIXME: Diagnose redundant specifiers.
DS.setObjCDeclQualifier(Qual);
+ if (Qual == ObjCDeclSpec::DQ_CSNullability)
+ DS.setNullability(Tok.getLocation(), Nullability);
+
ConsumeToken();
II = nullptr;
break;
@@ -878,17 +1271,28 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
ParseObjCTypeQualifierList(DS, context);
ParsedType Ty;
- if (isTypeSpecifierQualifier()) {
+ if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
// Parse an abstract declarator.
DeclSpec declSpec(AttrFactory);
declSpec.setObjCQualifiers(&DS);
- ParseSpecifierQualifierList(declSpec);
+ DeclSpecContext dsContext = DSC_normal;
+ if (context == Declarator::ObjCResultContext)
+ dsContext = DSC_objc_method_result;
+ ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
declSpec.SetRangeEnd(Tok.getLocation());
Declarator declarator(declSpec, context);
ParseDeclarator(declarator);
// If that's not invalid, extract a type.
if (!declarator.isInvalidType()) {
+ // Map a nullability specifier to a context-sensitive keyword attribute.
+ bool addedToDeclSpec = false;
+ if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)
+ addContextSensitiveTypeNullability(*this, declarator,
+ DS.getNullability(),
+ DS.getNullabilityLoc(),
+ addedToDeclSpec);
+
TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
if (!type.isInvalid())
Ty = type.get();
@@ -898,15 +1302,6 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
if (context == Declarator::ObjCParameterContext)
takeDeclAttributes(*paramAttrs, declarator);
}
- } else if (context == Declarator::ObjCResultContext &&
- Tok.is(tok::identifier)) {
- if (!Ident_instancetype)
- Ident_instancetype = PP.getIdentifierInfo("instancetype");
-
- if (Tok.getIdentifierInfo() == Ident_instancetype) {
- Ty = Actions.ActOnObjCInstanceType(Tok.getLocation());
- ConsumeToken();
- }
}
if (Tok.is(tok::r_paren))
@@ -1151,8 +1546,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
bool Parser::
ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
SmallVectorImpl<SourceLocation> &ProtocolLocs,
- bool WarnOnDeclarations,
- SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
+ bool WarnOnDeclarations, bool ForObjCContainer,
+ SourceLocation &LAngleLoc, SourceLocation &EndLoc,
+ bool consumeLastToken) {
assert(Tok.is(tok::less) && "expected <");
LAngleLoc = ConsumeToken(); // the "<"
@@ -1182,31 +1578,274 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
}
// Consume the '>'.
- if (ParseGreaterThanInTemplateList(EndLoc, /*ConsumeLastToken=*/true))
+ if (ParseGreaterThanInTemplateList(EndLoc, consumeLastToken,
+ /*ObjCGenericList=*/false))
return true;
// Convert the list of protocols identifiers into a list of protocol decls.
- Actions.FindProtocolDeclaration(WarnOnDeclarations,
+ Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
&ProtocolIdents[0], ProtocolIdents.size(),
Protocols);
return false;
}
-/// \brief Parse the Objective-C protocol qualifiers that follow a typename
-/// in a decl-specifier-seq, starting at the '<'.
-bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
+TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {
assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C");
- SourceLocation LAngleLoc, EndProtoLoc;
- SmallVector<Decl *, 8> ProtocolDecl;
- SmallVector<SourceLocation, 8> ProtocolLocs;
- bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
- if (EndProtoLoc.isValid())
- DS.SetRangeEnd(EndProtoLoc);
- return Result;
+
+ SourceLocation lAngleLoc;
+ SmallVector<Decl *, 8> protocols;
+ SmallVector<SourceLocation, 8> protocolLocs;
+ (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false,
+ lAngleLoc, rAngleLoc,
+ /*consumeLastToken=*/true);
+ TypeResult result = Actions.actOnObjCProtocolQualifierType(lAngleLoc,
+ protocols,
+ protocolLocs,
+ rAngleLoc);
+ if (result.isUsable()) {
+ Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id)
+ << FixItHint::CreateInsertion(lAngleLoc, "id")
+ << SourceRange(lAngleLoc, rAngleLoc);
+ }
+
+ return result;
+}
+
+/// Parse Objective-C type arguments or protocol qualifiers.
+///
+/// objc-type-arguments:
+/// '<' type-name '...'[opt] (',' type-name '...'[opt])* '>'
+///
+void Parser::parseObjCTypeArgsOrProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken,
+ bool warnOnIncompleteProtocols) {
+ assert(Tok.is(tok::less) && "Not at the start of type args or protocols");
+ SourceLocation lAngleLoc = ConsumeToken();
+
+ // Whether all of the elements we've parsed thus far are single
+ // identifiers, which might be types or might be protocols.
+ bool allSingleIdentifiers = true;
+ SmallVector<IdentifierInfo *, 4> identifiers;
+ SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs;
+
+ // Parse a list of comma-separated identifiers, bailing out if we
+ // see something different.
+ do {
+ // Parse a single identifier.
+ if (Tok.is(tok::identifier) &&
+ (NextToken().is(tok::comma) ||
+ NextToken().is(tok::greater) ||
+ NextToken().is(tok::greatergreater))) {
+ identifiers.push_back(Tok.getIdentifierInfo());
+ identifierLocs.push_back(ConsumeToken());
+ continue;
+ }
+
+ if (Tok.is(tok::code_completion)) {
+ // FIXME: Also include types here.
+ SmallVector<IdentifierLocPair, 4> identifierLocPairs;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
+ identifierLocs[i]));
+ }
+
+ QualType BaseT = Actions.GetTypeFromParser(baseType);
+ if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
+ } else {
+ Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(),
+ identifierLocPairs.size());
+ }
+ cutOffParsing();
+ return;
+ }
+
+ allSingleIdentifiers = false;
+ break;
+ } while (TryConsumeToken(tok::comma));
+
+ // If we parsed an identifier list, semantic analysis sorts out
+ // whether it refers to protocols or to type arguments.
+ if (allSingleIdentifiers) {
+ // Parse the closing '>'.
+ SourceLocation rAngleLoc;
+ (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken,
+ /*ObjCGenericList=*/true);
+
+ // Let Sema figure out what we parsed.
+ Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(),
+ baseType,
+ lAngleLoc,
+ identifiers,
+ identifierLocs,
+ rAngleLoc,
+ typeArgsLAngleLoc,
+ typeArgs,
+ typeArgsRAngleLoc,
+ protocolLAngleLoc,
+ protocols,
+ protocolRAngleLoc,
+ warnOnIncompleteProtocols);
+ return;
+ }
+
+ // We syntactically matched a type argument, so commit to parsing
+ // type arguments.
+
+ // Convert the identifiers into type arguments.
+ bool invalid = false;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ ParsedType typeArg
+ = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());
+ if (typeArg) {
+ DeclSpec DS(AttrFactory);
+ const char *prevSpec = nullptr;
+ unsigned diagID;
+ DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID,
+ typeArg, Actions.getASTContext().getPrintingPolicy());
+
+ // Form a declarator to turn this into a type.
+ Declarator D(DS, Declarator::TypeNameContext);
+ TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
+ if (fullTypeArg.isUsable())
+ typeArgs.push_back(fullTypeArg.get());
+ else
+ invalid = true;
+ } else {
+ invalid = true;
+ }
+ }
+
+ // Continue parsing type-names.
+ do {
+ TypeResult typeArg = ParseTypeName();
+
+ // Consume the '...' for a pack expansion.
+ SourceLocation ellipsisLoc;
+ TryConsumeToken(tok::ellipsis, ellipsisLoc);
+ if (typeArg.isUsable() && ellipsisLoc.isValid()) {
+ typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc);
+ }
+
+ if (typeArg.isUsable()) {
+ typeArgs.push_back(typeArg.get());
+ } else {
+ invalid = true;
+ }
+ } while (TryConsumeToken(tok::comma));
+
+ // Parse the closing '>'.
+ SourceLocation rAngleLoc;
+ (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken,
+ /*ObjCGenericList=*/true);
+
+ if (invalid) {
+ typeArgs.clear();
+ return;
+ }
+
+ // Record left/right angle locations.
+ typeArgsLAngleLoc = lAngleLoc;
+ typeArgsRAngleLoc = rAngleLoc;
+}
+
+void Parser::parseObjCTypeArgsAndProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken) {
+ assert(Tok.is(tok::less));
+
+ // Parse the first angle-bracket-delimited clause.
+ parseObjCTypeArgsOrProtocolQualifiers(baseType,
+ typeArgsLAngleLoc,
+ typeArgs,
+ typeArgsRAngleLoc,
+ protocolLAngleLoc,
+ protocols,
+ protocolLocs,
+ protocolRAngleLoc,
+ consumeLastToken,
+ /*warnOnIncompleteProtocols=*/false);
+
+ // An Objective-C object pointer followed by type arguments
+ // can then be followed again by a set of protocol references, e.g.,
+ // \c NSArray<NSView><NSTextDelegate>
+ if ((consumeLastToken && Tok.is(tok::less)) ||
+ (!consumeLastToken && NextToken().is(tok::less))) {
+ // If we aren't consuming the last token, the prior '>' is still hanging
+ // there. Consume it before we parse the protocol qualifiers.
+ if (!consumeLastToken)
+ ConsumeToken();
+
+ if (!protocols.empty()) {
+ SkipUntilFlags skipFlags = SkipUntilFlags();
+ if (!consumeLastToken)
+ skipFlags = skipFlags | StopBeforeMatch;
+ Diag(Tok, diag::err_objc_type_args_after_protocols)
+ << SourceRange(protocolLAngleLoc, protocolRAngleLoc);
+ SkipUntil(tok::greater, tok::greatergreater, skipFlags);
+ } else {
+ ParseObjCProtocolReferences(protocols, protocolLocs,
+ /*WarnOnDeclarations=*/false,
+ /*ForObjCContainer=*/false,
+ protocolLAngleLoc, protocolRAngleLoc,
+ consumeLastToken);
+ }
+ }
+}
+
+TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(
+ SourceLocation loc,
+ ParsedType type,
+ bool consumeLastToken,
+ SourceLocation &endLoc) {
+ assert(Tok.is(tok::less));
+ SourceLocation typeArgsLAngleLoc;
+ SmallVector<ParsedType, 4> typeArgs;
+ SourceLocation typeArgsRAngleLoc;
+ SourceLocation protocolLAngleLoc;
+ SmallVector<Decl *, 4> protocols;
+ SmallVector<SourceLocation, 4> protocolLocs;
+ SourceLocation protocolRAngleLoc;
+
+ // Parse type arguments and protocol qualifiers.
+ parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs,
+ typeArgsRAngleLoc, protocolLAngleLoc,
+ protocols, protocolLocs,
+ protocolRAngleLoc, consumeLastToken);
+
+ // Compute the location of the last token.
+ if (consumeLastToken)
+ endLoc = PrevTokLocation;
+ else
+ endLoc = Tok.getLocation();
+
+ return Actions.actOnObjCTypeArgsAndProtocolQualifiers(
+ getCurScope(),
+ loc,
+ type,
+ typeArgsLAngleLoc,
+ typeArgs,
+ typeArgsRAngleLoc,
+ protocolLAngleLoc,
+ protocols,
+ protocolLocs,
+ protocolRAngleLoc);
}
void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
@@ -1308,6 +1947,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
// Install the declarator into the interface decl.
+ FD.D.setObjCIvar(true);
Decl *Field = Actions.ActOnIvar(
getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
FD.BitfieldSize, visibility);
@@ -1416,8 +2056,9 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
SmallVector<Decl *, 8> ProtocolRefs;
SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc))
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
+ LAngleLoc, EndProtoLoc,
+ /*consumeLastToken=*/true))
return DeclGroupPtrTy();
Decl *ProtoType =
@@ -1467,6 +2108,22 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
Decl *ObjCImpDecl = nullptr;
+ // Neither a type parameter list nor a list of protocol references is
+ // permitted here. Parse and diagnose them.
+ if (Tok.is(tok::less)) {
+ SourceLocation lAngleLoc, rAngleLoc;
+ SmallVector<IdentifierLocPair, 8> protocolIdents;
+ SourceLocation diagLoc = Tok.getLocation();
+ if (parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents,
+ rAngleLoc)) {
+ Diag(diagLoc, diag::err_objc_parameterized_implementation)
+ << SourceRange(diagLoc, PrevTokLocation);
+ } else if (lAngleLoc.isValid()) {
+ Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier)
+ << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc));
+ }
+ }
+
if (Tok.is(tok::l_paren)) {
// we have a category implementation.
ConsumeParen();
@@ -1495,9 +2152,14 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
rparenLoc = ConsumeParen();
if (Tok.is(tok::less)) { // we have illegal '<' try to recover
Diag(Tok, diag::err_unexpected_protocol_qualifier);
- AttributeFactory attr;
- DeclSpec DS(attr);
- (void)ParseObjCProtocolQualifiers(DS);
+ SourceLocation protocolLAngleLoc, protocolRAngleLoc;
+ SmallVector<Decl *, 4> protocols;
+ SmallVector<SourceLocation, 4> protocolLocs;
+ (void)ParseObjCProtocolReferences(protocols, protocolLocs,
+ /*warnOnIncompleteProtocols=*/false,
+ /*ForObjCContainer=*/false,
+ protocolLAngleLoc, protocolRAngleLoc,
+ /*consumeLastToken=*/true);
}
ObjCImpDecl = Actions.ActOnStartCategoryImplementation(
AtLoc, nameId, nameLoc, categoryId,
@@ -1525,10 +2187,15 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
Diag(Tok, diag::err_unexpected_protocol_qualifier);
- // try to recover.
- AttributeFactory attr;
- DeclSpec DS(attr);
- (void)ParseObjCProtocolQualifiers(DS);
+
+ SourceLocation protocolLAngleLoc, protocolRAngleLoc;
+ SmallVector<Decl *, 4> protocols;
+ SmallVector<SourceLocation, 4> protocolLocs;
+ (void)ParseObjCProtocolReferences(protocols, protocolLocs,
+ /*warnOnIncompleteProtocols=*/false,
+ /*ForObjCContainer=*/false,
+ protocolLAngleLoc, protocolRAngleLoc,
+ /*consumeLastToken=*/true);
}
}
assert(ObjCImpDecl);
@@ -2169,8 +2836,8 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
InMessageExpressionRAIIObject InMessage(*this, true);
- if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
+ if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,
+ tok::annot_cxxscope))
TryAnnotateTypeOrScopeToken();
if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
@@ -2264,7 +2931,7 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
const Token &AfterNext = GetLookAheadToken(2);
- if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) {
+ if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
if (Tok.is(tok::identifier))
TryAnnotateTypeOrScopeToken();
@@ -2346,6 +3013,21 @@ ExprResult Parser::ParseObjCMessageExpression() {
ConsumeToken(); // the type name
+ // Parse type arguments and protocol qualifiers.
+ if (Tok.is(tok::less)) {
+ SourceLocation NewEndLoc;
+ TypeResult NewReceiverType
+ = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType,
+ /*consumeLastToken=*/true,
+ NewEndLoc);
+ if (!NewReceiverType.isUsable()) {
+ SkipUntil(tok::r_square, StopAtSemi);
+ return ExprError();
+ }
+
+ ReceiverType = NewReceiverType.get();
+ }
+
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ReceiverType, nullptr);
@@ -2890,9 +3572,8 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
- Tok.is(tok::colon)) &&
- "Inline objective-c method not starting with '{' or 'try' or ':'");
+ assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
+ "Inline objective-c method not starting with '{' or 'try' or ':'");
// Enter a scope for the method or c-function body.
ParseScope BodyScope(this,
parseMethod
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index 764619a..0113a31 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -30,24 +30,39 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
// E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
// TODO: add other combined directives in topological order.
const OpenMPDirectiveKind F[][3] = {
- { OMPD_for, OMPD_simd, OMPD_for_simd },
- { OMPD_parallel, OMPD_for, OMPD_parallel_for },
- { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
- { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
- };
+ {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
+ OMPD_cancellation_point},
+ {OMPD_for, OMPD_simd, OMPD_for_simd},
+ {OMPD_parallel, OMPD_for, OMPD_parallel_for},
+ {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
+ {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}};
auto Tok = P.getCurToken();
auto DKind =
Tok.isAnnotation()
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
+ bool TokenMatched = false;
for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
- if (DKind == F[i][0]) {
+ if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
+ TokenMatched =
+ (i == 0) &&
+ !P.getPreprocessor().getSpelling(Tok).compare("cancellation");
+ } else {
+ TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
+ }
+ if (TokenMatched) {
Tok = P.getPreprocessor().LookAhead(0);
auto SDKind =
Tok.isAnnotation()
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
- if (SDKind == F[i][1]) {
+ if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
+ TokenMatched =
+ (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point");
+ } else {
+ TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
+ }
+ if (TokenMatched) {
P.ConsumeToken();
DKind = F[i][2];
}
@@ -94,6 +109,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_taskgroup:
case OMPD_flush:
case OMPD_for:
case OMPD_for_simd:
@@ -109,6 +125,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_atomic:
case OMPD_target:
case OMPD_teams:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
break;
@@ -128,7 +146,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
-/// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
+/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup'
+/// {clause}
/// annot_pragma_openmp_end
///
StmtResult
@@ -143,6 +162,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeToken(), EndLoc;
auto DKind = ParseOpenMPDirectiveKind(*this);
+ OpenMPDirectiveKind CancelRegion = OMPD_unknown;
// Name of critical directive.
DeclarationNameInfo DirName;
StmtResult Directive = StmtError();
@@ -176,6 +196,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
if (!StandAloneAllowed) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind);
@@ -198,7 +220,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target:
- case OMPD_teams: {
+ case OMPD_teams:
+ case OMPD_taskgroup: {
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
@@ -214,6 +237,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
}
T.consumeClose();
}
+ } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
+ CancelRegion = ParseOpenMPDirectiveKind(*this);
+ if (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeToken();
}
if (isOpenMPLoopDirective(DKind))
@@ -229,6 +256,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
? OMPC_unknown
: FlushHasClause ? OMPC_flush
: getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
FlushHasClause = false;
OMPClause *Clause =
ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
@@ -241,6 +269,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
// Skip ',' if any.
if (Tok.is(tok::comma))
ConsumeToken();
+ Actions.EndOpenMPClause();
}
// End location of the directive.
EndLoc = Tok.getLocation();
@@ -257,17 +286,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
// Parse statement
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
- if (!AssociatedStmt.isUsable()) {
- Actions.ActOnCapturedRegionError();
- CreateDirective = false;
- } else {
- AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
- CreateDirective = AssociatedStmt.isUsable();
- }
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+ CreateDirective = AssociatedStmt.isUsable();
}
if (CreateDirective)
Directive = Actions.ActOnOpenMPExecutableDirective(
- DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
+ DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
+ EndLoc);
// Exit scope.
Actions.EndOpenMPDSABlock(Directive.get());
@@ -453,6 +478,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_copyin:
case OMPC_copyprivate:
case OMPC_flush:
+ case OMPC_depend:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
@@ -674,6 +700,8 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// 'copyprivate' '(' list ')'
/// flush-clause:
/// 'flush' '(' list ')'
+/// depend-clause:
+/// 'depend' '(' in | out | inout : list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
@@ -683,6 +711,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
CXXScopeSpec ReductionIdScopeSpec;
UnqualifiedId ReductionId;
bool InvalidReductionId = false;
+ OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
+ SourceLocation DepLoc;
+
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
@@ -706,10 +737,30 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
} else {
Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
}
+ } else if (Kind == OMPC_depend) {
+ // Handle dependency type for depend clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+ DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ DepLoc = Tok.getLocation();
+
+ if (DepKind == OMPC_DEPEND_unknown) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ } else {
+ ConsumeToken();
+ }
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+ } else {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
+ }
}
SmallVector<Expr *, 5> Vars;
- bool IsComma = !InvalidReductionId;
+ bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
+ ((Kind == OMPC_reduction) && !InvalidReductionId) ||
+ ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -753,13 +804,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
// Parse ')'.
T.consumeClose();
- if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
+ if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
+ (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
+ InvalidReductionId)
return nullptr;
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
ReductionIdScopeSpec,
ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
- : DeclarationNameInfo());
+ : DeclarationNameInfo(),
+ DepKind, DepLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 473be54..892d3c6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -198,9 +198,12 @@ void Parser::initializePragmaHandlers() {
OpenMPHandler.reset(new PragmaNoOpenMPHandler());
PP.AddPragmaHandler(OpenMPHandler.get());
- if (getLangOpts().MicrosoftExt) {
+ if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
MSCommentHandler.reset(new PragmaCommentHandler(Actions));
PP.AddPragmaHandler(MSCommentHandler.get());
+ }
+
+ if (getLangOpts().MicrosoftExt) {
MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
MSPointersToMembers.reset(new PragmaMSPointersToMembers());
@@ -261,9 +264,12 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(OpenMPHandler.get());
OpenMPHandler.reset();
- if (getLangOpts().MicrosoftExt) {
+ if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
PP.RemovePragmaHandler(MSCommentHandler.get());
MSCommentHandler.reset();
+ }
+
+ if (getLangOpts().MicrosoftExt) {
PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
MSDetectMismatchHandler.reset();
PP.RemovePragmaHandler(MSPointersToMembers.get());
@@ -793,8 +799,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
"PragmaLoopHintInfo::Toks must contain at least one token.");
// If no option is specified the argument is assumed to be a constant expr.
+ bool OptionUnroll = false;
bool StateOption = false;
- if (OptionInfo) { // Pragma unroll does not specify an option.
+ if (OptionInfo) { // Pragma Unroll does not specify an option.
+ OptionUnroll = OptionInfo->isStr("unroll");
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
.Case("vectorize", true)
.Case("interleave", true)
@@ -806,19 +814,20 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
if (Toks[0].is(tok::eof)) {
ConsumeToken(); // The annotation token.
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
- << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll;
+ << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
return false;
}
// Validate the argument.
if (StateOption) {
ConsumeToken(); // The annotation token.
- bool OptionUnroll = OptionInfo->isStr("unroll");
SourceLocation StateLoc = Toks[0].getLocation();
IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
- if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
- : !StateInfo->isStr("enable")) &&
- !StateInfo->isStr("disable"))) {
+ if (!StateInfo ||
+ ((OptionUnroll ? !StateInfo->isStr("full")
+ : !StateInfo->isStr("enable") &&
+ !StateInfo->isStr("assume_safety")) &&
+ !StateInfo->isStr("disable"))) {
Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
<< /*FullKeyword=*/OptionUnroll;
return false;
@@ -900,6 +909,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
<< "visibility";
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -911,6 +921,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_vis);
Toks[0].setLocation(VisLoc);
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(
const_cast<void*>(static_cast<const void*>(VisType)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1030,6 +1041,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_pack);
Toks[0].setLocation(PackLoc);
+ Toks[0].setAnnotationEndLoc(RParenLoc);
Toks[0].setAnnotationValue(static_cast<void*>(Info));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
@@ -1048,6 +1060,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
const IdentifierInfo *II = Tok.getIdentifierInfo();
if (II->isStr("on")) {
Kind = Sema::PMSST_ON;
@@ -1073,6 +1086,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_msstruct);
Toks[0].setLocation(MSStructTok.getLocation());
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1128,6 +1142,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1142,6 +1157,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_align);
Toks[0].setLocation(FirstTok.getLocation());
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1285,6 +1301,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
pragmaUnusedTok.setLocation(WeakLoc);
+ pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Toks[1] = WeakName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
@@ -1297,6 +1314,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weak);
pragmaUnusedTok.setLocation(WeakLoc);
+ pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Toks[1] = WeakName;
PP.EnterTokenStream(Toks, 2,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
@@ -1342,6 +1360,7 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
pragmaRedefTok.startToken();
pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
pragmaRedefTok.setLocation(RedefLoc);
+ pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Toks[1] = RedefName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
@@ -1364,6 +1383,7 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_fp_contract);
Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setAnnotationEndLoc(Tok.getLocation());
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(OOS)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1423,6 +1443,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
Toks[0].setKind(tok::annot_pragma_opencl_extension);
Toks[0].setLocation(NameLoc);
Toks[0].setAnnotationValue(data.getOpaqueValue());
+ Toks[0].setAnnotationEndLoc(StateLoc);
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
@@ -1471,7 +1492,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
Token *Toks = new Token[Pragma.size()];
std::copy(Pragma.begin(), Pragma.end(), Toks);
PP.EnterTokenStream(Toks, Pragma.size(),
- /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
+ /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true);
}
/// \brief Handle '#pragma pointers_to_members'
@@ -1554,6 +1575,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1565,6 +1587,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
AnnotTok.setLocation(PointersToMembersLoc);
+ AnnotTok.setAnnotationEndLoc(EndLoc);
AnnotTok.setAnnotationValue(
reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
PP.EnterToken(AnnotTok);
@@ -1644,6 +1667,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1656,6 +1680,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
AnnotTok.setLocation(VtorDispLoc);
+ AnnotTok.setAnnotationEndLoc(EndLoc);
AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
PP.EnterToken(AnnotTok);
@@ -1672,10 +1697,13 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_pragma);
AnnotTok.setLocation(Tok.getLocation());
+ AnnotTok.setAnnotationEndLoc(Tok.getLocation());
SmallVector<Token, 8> TokenVector;
// Suck up all of the tokens before the eod.
- for (; Tok.isNot(tok::eod); PP.Lex(Tok))
+ for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
TokenVector.push_back(Tok);
+ AnnotTok.setAnnotationEndLoc(Tok.getLocation());
+ }
// Add a sentinal EoF token to the end of the list.
TokenVector.push_back(EoF);
// We must allocate this array with new because EnterTokenStream is going to
@@ -1786,6 +1814,14 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
return;
}
+ // On PS4, issue a warning about any pragma comments other than
+ // #pragma comment lib.
+ if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
+ << II->getName();
+ return;
+ }
+
// Read the optional string if present.
PP.Lex(Tok);
std::string ArgumentString;
@@ -1920,6 +1956,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// loop-hint-keyword:
/// 'enable'
/// 'disable'
+/// 'assume_safety'
///
/// unroll-hint-keyword:
/// 'full'
@@ -1994,6 +2031,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
LoopHintTok.startToken();
LoopHintTok.setKind(tok::annot_pragma_loop_hint);
LoopHintTok.setLocation(PragmaName.getLocation());
+ LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
TokenList.push_back(LoopHintTok);
}
@@ -2076,6 +2114,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
TokenArray[0].startToken();
TokenArray[0].setKind(tok::annot_pragma_loop_hint);
TokenArray[0].setLocation(PragmaName.getLocation());
+ TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
/*OwnsTokens=*/true);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
index 2a5f840..b658cef 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -119,15 +119,12 @@ namespace {
class StatementFilterCCC : public CorrectionCandidateCallback {
public:
StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
- WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) ||
- nextTok.is(tok::identifier) || nextTok.is(tok::star) ||
- nextTok.is(tok::amp) || nextTok.is(tok::l_square);
- WantExpressionKeywords = nextTok.is(tok::l_paren) ||
- nextTok.is(tok::identifier) ||
- nextTok.is(tok::arrow) || nextTok.is(tok::period);
- WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) ||
- nextTok.is(tok::identifier) ||
- nextTok.is(tok::l_brace);
+ WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
+ tok::identifier, tok::star, tok::amp);
+ WantExpressionKeywords =
+ nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
+ WantRemainingKeywords =
+ nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
WantCXXNamedCasts = false;
}
@@ -408,12 +405,6 @@ StmtResult Parser::ParseExprStatement() {
return Actions.ActOnExprStmt(Expr);
}
-StmtResult Parser::ParseSEHTryBlock() {
- assert(Tok.is(tok::kw___try) && "Expected '__try'");
- SourceLocation Loc = ConsumeToken();
- return ParseSEHTryBlockCommon(Loc);
-}
-
/// ParseSEHTryBlockCommon
///
/// seh-try-block:
@@ -423,8 +414,11 @@ StmtResult Parser::ParseSEHTryBlock() {
/// seh-except-block
/// seh-finally-block
///
-StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
- if(Tok.isNot(tok::l_brace))
+StmtResult Parser::ParseSEHTryBlock() {
+ assert(Tok.is(tok::kw___try) && "Expected '__try'");
+ SourceLocation TryLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
@@ -441,7 +435,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
SourceLocation Loc = ConsumeToken();
Handler = ParseSEHFinallyBlock(Loc);
} else {
- return StmtError(Diag(Tok,diag::err_seh_expected_handler));
+ return StmtError(Diag(Tok, diag::err_seh_expected_handler));
}
if(Handler.isInvalid())
@@ -466,14 +460,21 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if (ExpectAndConsume(tok::l_paren))
return StmtError();
- ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope);
+ ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
+ Scope::SEHExceptScope);
if (getLangOpts().Borland) {
Ident__exception_info->setIsPoisoned(false);
Ident___exception_info->setIsPoisoned(false);
Ident_GetExceptionInfo->setIsPoisoned(false);
}
- ExprResult FilterExpr(ParseExpression());
+
+ ExprResult FilterExpr;
+ {
+ ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
+ Scope::SEHFilterScope);
+ FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ }
if (getLangOpts().Borland) {
Ident__exception_info->setIsPoisoned(true);
@@ -487,6 +488,9 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if (ExpectAndConsume(tok::r_paren))
return StmtError();
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
+
StmtResult Block(ParseCompoundStatement());
if(Block.isInvalid())
@@ -500,16 +504,24 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
/// seh-finally-block:
/// '__finally' compound-statement
///
-StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
+StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
raii2(Ident___abnormal_termination, false),
raii3(Ident_AbnormalTermination, false);
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
+
+ ParseScope FinallyScope(this, 0);
+ Actions.ActOnStartSEHFinallyBlock();
+
StmtResult Block(ParseCompoundStatement());
- if(Block.isInvalid())
+ if(Block.isInvalid()) {
+ Actions.ActOnAbortSEHFinallyBlock();
return Block;
+ }
- return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get());
+ return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
}
/// Handle __leave
@@ -1253,7 +1265,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// We have incremented the mangling number for the SwitchScope and the
// InnerScope, which is one too many.
if (C99orCXX)
- getCurScope()->decrementMSLocalManglingNumber();
+ getCurScope()->decrementMSManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1412,7 +1424,7 @@ bool Parser::isForRangeIdentifier() {
if (Next.is(tok::colon))
return true;
- if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) {
+ if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
TentativeParsingAction PA(*this);
ConsumeToken();
SkipCXX11Attributes();
@@ -1674,6 +1686,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
FirstPart.get(),
Collection.get(),
T.getCloseLocation());
+ } else {
+ // In OpenMP loop region loop control variable must be captured and be
+ // private. Perform analysis of first part (if any).
+ if (getLangOpts().OpenMP && FirstPart.isUsable()) {
+ Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
+ }
}
// C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
@@ -1695,7 +1713,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// It will only be incremented if the body contains other things that would
// normally increment the mangling number (like a compound statement).
if (C99orCXXorObjC)
- getCurScope()->decrementMSLocalManglingNumber();
+ getCurScope()->decrementMSManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
index 7bf4da6..8cdae6a 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
@@ -512,8 +512,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
llvm::SourceMgr TempSrcMgr;
llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
- MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default,
- Ctx);
+ MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default,
+ llvm::CodeModel::Default, Ctx);
std::unique_ptr<llvm::MemoryBuffer> Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
@@ -530,7 +530,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
std::unique_ptr<llvm::MCInstPrinter> IP(
- TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
+ TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
// Change to the Intel dialect.
Parser->setAssemblerDialect(1);
@@ -615,6 +615,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
msAsm = true;
return ParseMicrosoftAsmStatement(AsmLoc);
}
+
DeclSpec DS(AttrFactory);
SourceLocation Loc = Tok.getLocation();
ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
@@ -639,6 +640,15 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
T.consumeOpen();
ExprResult AsmString(ParseAsmStringLiteral());
+
+ // Check if GNU-style InlineAsm is disabled.
+ // Error on anything other than empty string.
+ if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) {
+ const auto *SL = cast<StringLiteral>(AsmString.get());
+ if (!SL->getString().trim().empty())
+ Diag(Loc, diag::err_gnu_inline_asm_disabled);
+ }
+
if (AsmString.isInvalid()) {
// Consume up to and including the closing paren.
T.skipToEnd();
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 53de72c..3a964dd 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
@@ -61,7 +62,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
- assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
+ assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&
"Token does not start a template declaration.");
// Enter template-parameter scope.
@@ -115,7 +116,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SmallVector<Decl*, 4> TemplateParams;
if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
TemplateParams, LAngleLoc, RAngleLoc)) {
- // Skip until the semi-colon or a }.
+ // Skip until the semi-colon or a '}'.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
TryConsumeToken(tok::semi);
return nullptr;
@@ -131,10 +132,21 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
if (!TemplateParams.empty()) {
isSpecialization = false;
++CurTemplateDepthTracker;
+
+ if (TryConsumeToken(tok::kw_requires)) {
+ ExprResult ER =
+ Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression());
+ if (!ER.isUsable()) {
+ // Skip until the semi-colon or a '}'.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ TryConsumeToken(tok::semi);
+ return nullptr;
+ }
+ }
} else {
LastParamListWasEmpty = true;
}
- } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
+ } while (Tok.isOneOf(tok::kw_export, tok::kw_template));
// Parse the actual template declaration.
return ParseSingleDeclarationAfterTemplate(Context,
@@ -366,7 +378,7 @@ Parser::ParseTemplateParameterList(unsigned Depth,
// Did we find a comma or the end of the template parameter list?
if (Tok.is(tok::comma)) {
ConsumeToken();
- } else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::greater, tok::greatergreater)) {
// Don't consume this... that's done by template parser.
break;
} else {
@@ -483,7 +495,7 @@ Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
- assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
+ assert(Tok.isOneOf(tok::kw_class, tok::kw_typename) &&
"A type-parameter starts with 'class' or 'typename'");
// Consume the 'class' or 'typename' keyword.
@@ -505,8 +517,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
- Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,
+ tok::greatergreater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
@@ -566,7 +578,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// or greater appear immediately or after 'struct'. In the latter case,
// replace the keyword with 'class'.
if (!TryConsumeToken(tok::kw_class)) {
- bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
+ bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
if (Tok.is(tok::kw_typename)) {
Diag(Tok.getLocation(),
@@ -576,9 +588,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
<< (!getLangOpts().CPlusPlus1z
? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint());
- } else if (Next.is(tok::identifier) || Next.is(tok::comma) ||
- Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::ellipsis)) {
+ } else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,
+ tok::greatergreater, tok::ellipsis)) {
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
@@ -603,8 +614,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
- Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,
+ tok::greatergreater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
@@ -727,11 +738,16 @@ void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,
///
/// \param RAngleLoc the location of the consumed '>'.
///
-/// \param ConsumeLastToken if true, the '>' is not consumed.
+/// \param ConsumeLastToken if true, the '>' is consumed.
+///
+/// \param ObjCGenericList if true, this is the '>' closing an Objective-C
+/// type parameter or type argument list, rather than a C++ template parameter
+/// or argument list.
///
/// \returns true, if current token does not start with '>', false otherwise.
bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
- bool ConsumeLastToken) {
+ bool ConsumeLastToken,
+ bool ObjCGenericList) {
// What will be left once we've consumed the '>'.
tok::TokenKind RemainingToken;
const char *ReplacementStr = "> >";
@@ -772,41 +788,44 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
// the token isn't '>>' or '>>>'.
// '>>>' is for CUDA, where this sequence of characters is parsed into
// tok::greatergreatergreater, rather than two separate tokens.
-
+ //
+ // We always allow this for Objective-C type parameter and type argument
+ // lists.
RAngleLoc = Tok.getLocation();
-
- // The source range of the '>>' or '>=' at the start of the token.
- CharSourceRange ReplacementRange =
- CharSourceRange::getCharRange(RAngleLoc,
- Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(),
- getLangOpts()));
-
- // A hint to put a space between the '>>'s. In order to make the hint as
- // clear as possible, we include the characters either side of the space in
- // the replacement, rather than just inserting a space at SecondCharLoc.
- FixItHint Hint1 = FixItHint::CreateReplacement(ReplacementRange,
- ReplacementStr);
-
- // A hint to put another space after the token, if it would otherwise be
- // lexed differently.
- FixItHint Hint2;
Token Next = NextToken();
- if ((RemainingToken == tok::greater ||
- RemainingToken == tok::greatergreater) &&
- (Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::greatergreatergreater) || Next.is(tok::equal) ||
- Next.is(tok::greaterequal) || Next.is(tok::greatergreaterequal) ||
- Next.is(tok::equalequal)) &&
- areTokensAdjacent(Tok, Next))
- Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
-
- unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
- if (getLangOpts().CPlusPlus11 &&
- (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))
- DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
- else if (Tok.is(tok::greaterequal))
- DiagId = diag::err_right_angle_bracket_equal_needs_space;
- Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2;
+ if (!ObjCGenericList) {
+ // The source range of the '>>' or '>=' at the start of the token.
+ CharSourceRange ReplacementRange =
+ CharSourceRange::getCharRange(RAngleLoc,
+ Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(),
+ getLangOpts()));
+
+ // A hint to put a space between the '>>'s. In order to make the hint as
+ // clear as possible, we include the characters either side of the space in
+ // the replacement, rather than just inserting a space at SecondCharLoc.
+ FixItHint Hint1 = FixItHint::CreateReplacement(ReplacementRange,
+ ReplacementStr);
+
+ // A hint to put another space after the token, if it would otherwise be
+ // lexed differently.
+ FixItHint Hint2;
+ if ((RemainingToken == tok::greater ||
+ RemainingToken == tok::greatergreater) &&
+ (Next.isOneOf(tok::greater, tok::greatergreater,
+ tok::greatergreatergreater, tok::equal,
+ tok::greaterequal, tok::greatergreaterequal,
+ tok::equalequal)) &&
+ areTokensAdjacent(Tok, Next))
+ Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
+
+ unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
+ if (getLangOpts().CPlusPlus11 &&
+ (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))
+ DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
+ else if (Tok.is(tok::greaterequal))
+ DiagId = diag::err_right_angle_bracket_equal_needs_space;
+ Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2;
+ }
// Strip the initial '>' from the token.
if (RemainingToken == tok::equal && Next.is(tok::equal) &&
@@ -885,7 +904,8 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
}
}
- return ParseGreaterThanInTemplateList(RAngleLoc, ConsumeLastToken);
+ return ParseGreaterThanInTemplateList(RAngleLoc, ConsumeLastToken,
+ /*ObjCGenericList=*/false);
}
/// \brief Replace the tokens that form a simple-template-id with an
@@ -1054,8 +1074,7 @@ void Parser::AnnotateTemplateIdTokenAsType() {
/// \brief Determine whether the given token can end a template argument.
static bool isEndOfTemplateArgument(Token Tok) {
- return Tok.is(tok::comma) || Tok.is(tok::greater) ||
- Tok.is(tok::greatergreater);
+ return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater);
}
/// \brief Parse a C++ template template argument.
@@ -1216,7 +1235,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
ConsumeToken();
// If we have a '>' or a ',' then this is a template argument list.
- return Tok.is(tok::greater) || Tok.is(tok::comma);
+ return Tok.isOneOf(tok::greater, tok::comma);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
@@ -1301,7 +1320,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
// To restore the context after late parsing.
- Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
+ Sema::ContextRAII GlobalSavedContext(
+ Actions, Actions.Context.getTranslationUnitDecl());
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
@@ -1337,8 +1357,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
- && "Inline method not starting with '{', ':' or 'try'");
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) &&
+ "Inline method not starting with '{', ':' or 'try'");
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
index abf16fa..9d2a2b9 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -179,8 +179,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
ConsumeToken();
// Skip attributes.
- while (Tok.is(tok::l_square) || Tok.is(tok::kw___attribute) ||
- Tok.is(tok::kw___declspec) || Tok.is(tok::kw_alignas)) {
+ while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
+ tok::kw_alignas)) {
if (Tok.is(tok::l_square)) {
ConsumeBracket();
if (!SkipUntil(tok::r_square))
@@ -195,8 +195,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
}
}
- if ((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
+ tok::annot_template_id) &&
TryAnnotateCXXScopeToken())
return TPResult::Error;
if (Tok.is(tok::annot_cxxscope))
@@ -289,7 +289,7 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
return TPR;
// [GNU] simple-asm-expr[opt] attributes[opt]
- if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute))
return TPResult::True;
// initializer[opt]
@@ -370,8 +370,7 @@ bool Parser::isCXXConditionDeclaration() {
if (TPR == TPResult::Ambiguous) {
// '='
// [GNU] simple-asm-expr[opt] attributes[opt]
- if (Tok.is(tok::equal) ||
- Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute))
TPR = TPResult::True;
else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
TPR = TPResult::True;
@@ -448,7 +447,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
// the abstract declarator we encounter a '>', '>>' (in C++0x), or
// ',', this is a type-id. Otherwise, it's an expression.
} else if (Context == TypeIdAsTemplateArgument &&
- (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+ (Tok.isOneOf(tok::greater, tok::comma) ||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
TPR = TPResult::True;
isAmbiguous = true;
@@ -624,18 +623,17 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (true) {
- if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+ if (Tok.isOneOf(tok::coloncolon, tok::identifier))
if (TryAnnotateCXXScopeToken(true))
return TPResult::Error;
- if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
- Tok.is(tok::ampamp) ||
+ if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
// ptr-operator
ConsumeToken();
- while (Tok.is(tok::kw_const) ||
- Tok.is(tok::kw_volatile) ||
- Tok.is(tok::kw_restrict))
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
+ tok::kw__Nonnull, tok::kw__Nullable,
+ tok::kw__Null_unspecified))
ConsumeToken();
} else {
return TPResult::True;
@@ -803,7 +801,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
if (Tok.is(tok::ellipsis))
ConsumeToken();
- if ((Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+ if ((Tok.isOneOf(tok::identifier, tok::kw_operator) ||
(Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) ||
NextToken().is(tok::kw_operator)))) &&
mayHaveIdentifier) {
@@ -833,14 +831,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// '(' declarator ')'
// '(' attributes declarator ')'
// '(' abstract-declarator ')'
- if (Tok.is(tok::kw___attribute) ||
- Tok.is(tok::kw___declspec) ||
- Tok.is(tok::kw___cdecl) ||
- Tok.is(tok::kw___stdcall) ||
- Tok.is(tok::kw___fastcall) ||
- Tok.is(tok::kw___thiscall) ||
- Tok.is(tok::kw___vectorcall) ||
- Tok.is(tok::kw___unaligned))
+ if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,
+ tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,
+ tok::kw___vectorcall, tok::kw___unaligned))
return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
if (TPR != TPResult::Ambiguous)
@@ -1015,9 +1008,8 @@ class TentativeParseCCC : public CorrectionCandidateCallback {
public:
TentativeParseCCC(const Token &Next) {
WantRemainingKeywords = false;
- WantTypeSpecifiers = Next.is(tok::l_paren) || Next.is(tok::r_paren) ||
- Next.is(tok::greater) || Next.is(tok::l_brace) ||
- Next.is(tok::identifier);
+ WantTypeSpecifiers = Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater,
+ tok::l_brace, tok::identifier);
}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
@@ -1201,8 +1193,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
- if (Next.is(tok::kw_new) || // ::new
- Next.is(tok::kw_delete)) // ::delete
+ if (Next.isOneOf(tok::kw_new, // ::new
+ tok::kw_delete)) // ::delete
return TPResult::False;
}
// Fall through.
@@ -1221,9 +1213,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// 'friend'
// 'typedef'
// 'constexpr'
+ // 'concept'
case tok::kw_friend:
case tok::kw_typedef:
case tok::kw_constexpr:
+ case tok::kw_concept:
// storage-class-specifier
case tok::kw_register:
case tok::kw_static:
@@ -1284,6 +1278,10 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___ptr32:
case tok::kw___forceinline:
case tok::kw___unaligned:
+ case tok::kw__Nonnull:
+ case tok::kw__Nullable:
+ case tok::kw__Null_unspecified:
+ case tok::kw___kindof:
return TPResult::True;
// Borland
@@ -1387,7 +1385,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case_typename:
// In Objective-C, we might have a protocol-qualified type.
if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
- // Tentatively parse the
+ // Tentatively parse the protocol qualifiers.
TentativeParsingAction PA(*this);
ConsumeToken(); // The type token
@@ -1603,12 +1601,10 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
TPR = TPResult::False;
else {
const Token &Next = NextToken();
- if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
- Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||
- Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||
- Next.is(tok::l_square) || isCXX11VirtSpecifier(Next) ||
- Next.is(tok::l_brace) || Next.is(tok::kw_try) ||
- Next.is(tok::equal) || Next.is(tok::arrow))
+ if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,
+ tok::kw_throw, tok::kw_noexcept, tok::l_square,
+ tok::l_brace, tok::kw_try, tok::equal, tok::arrow) ||
+ isCXX11VirtSpecifier(Next))
// The next token cannot appear after a constructor-style initializer,
// and can appear next in a function definition. This must be a function
// declarator.
@@ -1729,8 +1725,8 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
// parameter-declaration-clause, and the last param is missing its default
// argument.
if (VersusTemplateArgument)
- return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True
- : TPResult::False;
+ return Tok.isOneOf(tok::equal, tok::r_paren) ? TPResult::True
+ : TPResult::False;
if (Tok.is(tok::equal)) {
// '=' assignment-expression
@@ -1783,13 +1779,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
return TPResult::Error;
// cv-qualifier-seq
- while (Tok.is(tok::kw_const) ||
- Tok.is(tok::kw_volatile) ||
- Tok.is(tok::kw_restrict) )
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict))
ConsumeToken();
// ref-qualifier[opt]
- if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+ if (Tok.isOneOf(tok::amp, tok::ampamp))
ConsumeToken();
// exception-specification
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index 7ccd209..e76f767 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -38,6 +38,26 @@ public:
return false;
}
};
+
+/// \brief RAIIObject to destroy the contents of a SmallVector of
+/// TemplateIdAnnotation pointers and clear the vector.
+class DestroyTemplateIdAnnotationsRAIIObj {
+ SmallVectorImpl<TemplateIdAnnotation *> &Container;
+
+public:
+ DestroyTemplateIdAnnotationsRAIIObj(
+ SmallVectorImpl<TemplateIdAnnotation *> &Container)
+ : Container(Container) {}
+
+ ~DestroyTemplateIdAnnotationsRAIIObj() {
+ for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
+ Container.begin(),
+ E = Container.end();
+ I != E; ++I)
+ (*I)->Destroy();
+ Container.clear();
+ }
+};
} // end anonymous namespace
IdentifierInfo *Parser::getSEHExceptKeyword() {
@@ -414,6 +434,15 @@ Parser::~Parser() {
PP.clearCodeCompletionHandler();
+ if (getLangOpts().DelayedTemplateParsing &&
+ !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) {
+ // If an ASTConsumer parsed delay-parsed templates in their
+ // HandleTranslationUnit() method, TemplateIds created there were not
+ // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in
+ // ParseTopLevelDecl(). Destroy them here.
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
+ }
+
assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
}
@@ -434,6 +463,10 @@ void Parser::Initialize() {
ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");
ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
+ ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull");
+ ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable");
+ ObjCTypeQuals[objc_null_unspecified]
+ = &PP.getIdentifierTable().get("null_unspecified");
}
Ident_instancetype = nullptr;
@@ -490,26 +523,6 @@ void Parser::Initialize() {
ConsumeToken();
}
-namespace {
- /// \brief RAIIObject to destroy the contents of a SmallVector of
- /// TemplateIdAnnotation pointers and clear the vector.
- class DestroyTemplateIdAnnotationsRAIIObj {
- SmallVectorImpl<TemplateIdAnnotation *> &Container;
- public:
- DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl<TemplateIdAnnotation *>
- &Container)
- : Container(Container) {}
-
- ~DestroyTemplateIdAnnotationsRAIIObj() {
- for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
- Container.begin(), E = Container.end();
- I != E; ++I)
- (*I)->Destroy();
- Container.clear();
- }
- };
-}
-
void Parser::LateTemplateParserCleanupCallback(void *P) {
// While this RAII helper doesn't bracket any actual work, the destructor will
// clean up annotations that were created during ActOnEndOfTranslationUnit
@@ -541,8 +554,14 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
return false;
case tok::annot_module_begin:
+ Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ return false;
+
case tok::annot_module_end:
- // FIXME: Update visibility based on the submodule we're in.
+ Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
ConsumeToken();
return false;
@@ -669,8 +688,18 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc;
+
ExprResult Result(ParseSimpleAsm(&EndLoc));
+ // Check if GNU-style InlineAsm is disabled.
+ // Empty asm string is allowed because it will not introduce
+ // any assembly code.
+ if (!(getLangOpts().GNUAsm || Result.isInvalid())) {
+ const auto *SL = cast<StringLiteral>(Result.get());
+ if (!SL->getString().trim().empty())
+ Diag(StartLoc, diag::err_gnu_inline_asm_disabled);
+ }
+
ExpectAndConsume(tok::semi, diag::err_expected_after,
"top-level asm block");
@@ -1048,7 +1077,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- Actions.ActOnFinishFunctionBody(Res, nullptr, false);
bool Delete = false;
SourceLocation KWLoc;
@@ -1076,6 +1104,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
SkipUntil(tok::semi);
}
+ Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
+ Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
return Res;
}
@@ -1383,14 +1413,35 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
// It's not something we know about. Leave it unannotated.
break;
- case Sema::NC_Type:
- Tok.setKind(tok::annot_typename);
- setTypeAnnotation(Tok, Classification.getType());
- Tok.setAnnotationEndLoc(NameLoc);
+ case Sema::NC_Type: {
+ SourceLocation BeginLoc = NameLoc;
if (SS.isNotEmpty())
- Tok.setLocation(SS.getBeginLoc());
+ BeginLoc = SS.getBeginLoc();
+
+ /// An Objective-C object type followed by '<' is a specialization of
+ /// a parameterized class type or a protocol-qualified type.
+ ParsedType Ty = Classification.getType();
+ if (getLangOpts().ObjC1 && NextToken().is(tok::less) &&
+ (Ty.get()->isObjCObjectType() ||
+ Ty.get()->isObjCObjectPointerType())) {
+ // Consume the name.
+ SourceLocation IdentifierLoc = ConsumeToken();
+ SourceLocation NewEndLoc;
+ TypeResult NewType
+ = parseObjCTypeArgsAndProtocolQualifiers(IdentifierLoc, Ty,
+ /*consumeLastToken=*/false,
+ NewEndLoc);
+ if (NewType.isUsable())
+ Ty = NewType.get();
+ }
+
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Ty);
+ Tok.setAnnotationEndLoc(Tok.getLocation());
+ Tok.setLocation(BeginLoc);
PP.AnnotateCachedTokens(Tok);
return ANK_Success;
+ }
case Sema::NC_Expression:
Tok.setKind(tok::annot_primary_expr);
@@ -1597,13 +1648,33 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
// A FixIt was applied as a result of typo correction
if (CorrectedII)
Tok.setIdentifierInfo(CorrectedII);
+
+ SourceLocation BeginLoc = Tok.getLocation();
+ if (SS.isNotEmpty()) // it was a C++ qualified type name.
+ BeginLoc = SS.getBeginLoc();
+
+ /// An Objective-C object type followed by '<' is a specialization of
+ /// a parameterized class type or a protocol-qualified type.
+ if (getLangOpts().ObjC1 && NextToken().is(tok::less) &&
+ (Ty.get()->isObjCObjectType() ||
+ Ty.get()->isObjCObjectPointerType())) {
+ // Consume the name.
+ SourceLocation IdentifierLoc = ConsumeToken();
+ SourceLocation NewEndLoc;
+ TypeResult NewType
+ = parseObjCTypeArgsAndProtocolQualifiers(IdentifierLoc, Ty,
+ /*consumeLastToken=*/false,
+ NewEndLoc);
+ if (NewType.isUsable())
+ Ty = NewType.get();
+ }
+
// This is a typename. Replace the current token in-place with an
// annotation type token.
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Ty);
Tok.setAnnotationEndLoc(Tok.getLocation());
- if (SS.isNotEmpty()) // it was a C++ qualified type name.
- Tok.setLocation(SS.getBeginLoc());
+ Tok.setLocation(BeginLoc);
// In case the tokens were cached, have Preprocessor replace
// them with the annotation token.
diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
index a0c9c1f..36d87eb 100644
--- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
+++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
@@ -58,6 +58,12 @@ namespace clang {
Active = false;
}
}
+ SuppressAccessChecks(SuppressAccessChecks &&Other)
+ : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
+ State(Other.State), Active(Other.Active) {
+ Other.Active = false;
+ }
+ void operator=(SuppressAccessChecks &&Other) = delete;
void done() {
assert(Active && "trying to end an inactive suppression");
@@ -87,8 +93,8 @@ namespace clang {
Sema::ParsingDeclState State;
bool Popped;
- ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
- void operator=(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
+ ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
+ void operator=(const ParsingDeclRAIIObject &) = delete;
public:
enum NoParent_t { NoParent };
@@ -244,8 +250,8 @@ namespace clang {
/// the way they used to be. This is used to handle __extension__ in the
/// parser.
class ExtensionRAIIObject {
- ExtensionRAIIObject(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
- void operator=(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
+ ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
+ void operator=(const ExtensionRAIIObject &) = delete;
DiagnosticsEngine &Diags;
public:
@@ -423,7 +429,13 @@ namespace clang {
if (P.Tok.is(Close)) {
LClose = (P.*Consumer)();
return false;
- }
+ } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
+ SourceLocation SemiLoc = P.ConsumeToken();
+ P.Diag(SemiLoc, diag::err_unexpected_semi)
+ << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
+ LClose = (P.*Consumer)();
+ return false;
+ }
return diagnoseMissingClose();
}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
index 1c82ee4..451ad07 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
@@ -89,9 +89,9 @@ namespace {
bool IsLeaf;
RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
- ~RopePieceBTreeNode() {}
- public:
+ ~RopePieceBTreeNode() = default;
+ public:
bool isLeaf() const { return IsLeaf; }
unsigned size() const { return Size; }
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
index 60cdcf7..be09a36 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
@@ -54,7 +54,7 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
if (Size == 0) return;
unsigned RealOffset = getMappedOffset(OrigOffset, true);
- assert(RealOffset+Size < Buffer.size() && "Invalid location");
+ assert(RealOffset+Size <= Buffer.size() && "Invalid location");
// Remove the dead characters.
Buffer.erase(RealOffset, Size);
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index f666a9b..f2ff48a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -117,6 +117,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
}
+namespace {
/// \brief Warn on logical operator errors in CFGBuilder
class LogicalErrorHandler : public CFGCallback {
Sema &S;
@@ -129,16 +130,15 @@ public:
return true;
// Recurse to children.
- for (ConstStmtRange SubStmts = E->children(); SubStmts; ++SubStmts)
- if (*SubStmts)
- if (const Expr *SubExpr = dyn_cast<Expr>(*SubStmts))
- if (HasMacroID(SubExpr))
- return true;
+ for (const Stmt *SubStmt : E->children())
+ if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
+ if (HasMacroID(SubExpr))
+ return true;
return false;
}
- void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {
+ void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override {
if (HasMacroID(B))
return;
@@ -147,7 +147,8 @@ public:
<< DiagRange << isAlwaysTrue;
}
- void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {
+ void compareBitwiseEquality(const BinaryOperator *B,
+ bool isAlwaysTrue) override {
if (HasMacroID(B))
return;
@@ -156,7 +157,7 @@ public:
<< DiagRange << isAlwaysTrue;
}
};
-
+} // namespace
//===----------------------------------------------------------------------===//
// Check for infinite self-recursion in functions
@@ -572,28 +573,29 @@ namespace {
/// ContainsReference - A visitor class to search for references to
/// a particular declaration (the needle) within any evaluated component of an
/// expression (recursively).
-class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
+class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {
bool FoundReference;
const DeclRefExpr *Needle;
public:
+ typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited;
+
ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
- : EvaluatedExprVisitor<ContainsReference>(Context),
- FoundReference(false), Needle(Needle) {}
+ : Inherited(Context), FoundReference(false), Needle(Needle) {}
- void VisitExpr(Expr *E) {
+ void VisitExpr(const Expr *E) {
// Stop evaluating if we already have a reference.
if (FoundReference)
return;
- EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
+ Inherited::VisitExpr(E);
}
- void VisitDeclRefExpr(DeclRefExpr *E) {
+ void VisitDeclRefExpr(const DeclRefExpr *E) {
if (E == Needle)
FoundReference = true;
else
- EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
+ Inherited::VisitDeclRefExpr(E);
}
bool doesContainReference() const { return FoundReference; }
@@ -852,7 +854,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
return false;
ContainsReference CR(S.Context, DRE);
- CR.Visit(const_cast<Expr*>(Initializer));
+ CR.Visit(Initializer);
if (CR.doesContainReference()) {
S.Diag(DRE->getLocStart(),
diag::warn_uninit_self_reference_in_init)
@@ -1332,9 +1334,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
public:
UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
- ~UninitValsDiagReporter() {
- flushDiagnostics();
- }
+ ~UninitValsDiagReporter() override { flushDiagnostics(); }
MappedType &getUses(const VarDecl *vd) {
if (!uses)
@@ -1438,7 +1438,7 @@ struct SortDiagBySourceLocation {
//===----------------------------------------------------------------------===//
namespace clang {
namespace threadSafety {
-
+namespace {
class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
Sema &S;
DiagList Warnings;
@@ -1463,7 +1463,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
<< CurrentFunction->getNameAsString());
- ONS.push_back(FNote);
+ ONS.push_back(std::move(FNote));
}
return ONS;
}
@@ -1477,7 +1477,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
<< CurrentFunction->getNameAsString());
- ONS.push_back(FNote);
+ ONS.push_back(std::move(FNote));
}
return ONS;
}
@@ -1490,7 +1490,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (!Loc.isValid())
Loc = FunLocation;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName);
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
public:
@@ -1516,7 +1516,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
<< Loc);
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
void handleUnmatchedUnlock(StringRef Kind, Name LockName,
@@ -1532,7 +1532,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch)
<< Kind << LockName << Received
<< Expected);
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override {
@@ -1566,10 +1566,10 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (LocLocked.isValid()) {
PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)
<< Kind);
- Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
+ Warnings.emplace_back(std::move(Warning), getNotes(Note));
return;
}
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
void handleExclusiveAndShared(StringRef Kind, Name LockName,
@@ -1580,7 +1580,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
<< Kind << LockName);
PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
<< Kind << LockName);
- Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
+ Warnings.emplace_back(std::move(Warning), getNotes(Note));
}
void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
@@ -1593,7 +1593,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
diag::warn_var_deref_requires_any_lock;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
<< D->getNameAsString() << getLockKindFromAccessKind(AK));
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
@@ -1628,9 +1628,9 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt VNote(D->getLocation(),
S.PDiag(diag::note_guarded_by_declared_here)
<< D->getNameAsString());
- Warnings.push_back(DelayedDiag(Warning, getNotes(Note, VNote)));
+ Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
} else
- Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
+ Warnings.emplace_back(std::move(Warning), getNotes(Note));
} else {
switch (POK) {
case POK_VarAccess:
@@ -1656,19 +1656,18 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
PartialDiagnosticAt Note(D->getLocation(),
S.PDiag(diag::note_guarded_by_declared_here)
<< D->getNameAsString());
- Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
+ Warnings.emplace_back(std::move(Warning), getNotes(Note));
} else
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
}
-
- virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
- SourceLocation Loc) override {
+ void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+ SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc,
S.PDiag(diag::warn_acquire_requires_negative_cap)
<< Kind << LockName << Neg);
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
@@ -1676,7 +1675,20 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
<< Kind << FunName << LockName);
- Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ Warnings.emplace_back(std::move(Warning), getNotes());
+ }
+
+ void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name,
+ SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc,
+ S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name);
+ Warnings.emplace_back(std::move(Warning), getNotes());
+ }
+
+ void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc,
+ S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name);
+ Warnings.emplace_back(std::move(Warning), getNotes());
}
void enterFunction(const FunctionDecl* FD) override {
@@ -1687,9 +1699,9 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
CurrentFunction = 0;
}
};
-
-}
-}
+} // namespace
+} // namespace threadSafety
+} // namespace clang
//===----------------------------------------------------------------------===//
// -Wconsumed
@@ -1704,7 +1716,7 @@ class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
DiagList Warnings;
public:
-
+
ConsumedWarningsHandler(Sema &S) : S(S) {}
void emitDiagnostics() override {
@@ -1720,8 +1732,8 @@ public:
StringRef VariableName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
VariableName);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnParamReturnTypestateMismatch(SourceLocation Loc,
@@ -1732,8 +1744,8 @@ public:
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_return_typestate_mismatch) << VariableName <<
ExpectedState << ObservedState);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
@@ -1741,16 +1753,16 @@ public:
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
StringRef TypeName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_for_unconsumable_type) << TypeName);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
@@ -1758,8 +1770,8 @@ public:
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
@@ -1767,8 +1779,8 @@ public:
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
@@ -1776,8 +1788,8 @@ public:
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
MethodName << VariableName << State);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+
+ Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
};
}}}
@@ -1874,6 +1886,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
AC.getCFGBuildOptions().AddImplicitDtors = true;
AC.getCFGBuildOptions().AddTemporaryDtors = true;
AC.getCFGBuildOptions().AddCXXNewAllocator = false;
+ AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
// Force that certain expressions appear as CFGElements in the CFG. This
// is used to speed up various analyses.
@@ -1981,7 +1994,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart()))
Reporter.setVerbose(true);
- threadSafety::runThreadSafetyAnalysis(AC, Reporter);
+ threadSafety::runThreadSafetyAnalysis(AC, Reporter,
+ &S.ThreadSafetyDeclCache);
Reporter.emitDiagnostics();
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index b2dc2d7..18e9a59 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -251,19 +251,16 @@ const char *CodeCompletionString::getTypedText() const {
return nullptr;
}
-const char *CodeCompletionAllocator::CopyString(StringRef String) {
- char *Mem = (char *)Allocate(String.size() + 1, 1);
- std::copy(String.begin(), String.end(), Mem);
- Mem[String.size()] = 0;
- return Mem;
-}
-
-const char *CodeCompletionAllocator::CopyString(Twine String) {
+const char *CodeCompletionAllocator::CopyString(const Twine &String) {
+ SmallString<128> Data;
+ StringRef Ref = String.toStringRef(Data);
// FIXME: It would be more efficient to teach Twine to tell us its size and
// then add a routine there to fill in an allocated char* with the contents
// of the string.
- SmallString<128> Data;
- return CopyString(String.toStringRef(Data));
+ char *Mem = (char *)Allocate(Ref.size() + 1, 1);
+ std::copy(Ref.begin(), Ref.end(), Mem);
+ Mem[Ref.size()] = 0;
+ return Mem;
}
StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
@@ -447,7 +444,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
if (Results[I].Hidden)
OS << " (Hidden)";
if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+ = Results[I].CreateCodeCompletionString(SemaRef, Context,
+ getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
@@ -465,7 +463,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
case CodeCompletionResult::RK_Macro: {
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+ = Results[I].CreateCodeCompletionString(SemaRef, Context,
+ getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
@@ -483,6 +482,31 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
}
}
+// This function is used solely to preserve the former presentation of overloads
+// by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString
+// needs to be improved for printing the newer and more detailed overload
+// chunks.
+static std::string getOverloadAsString(const CodeCompletionString &CCS) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+
+ for (auto &C : CCS) {
+ switch (C.Kind) {
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_ResultType:
+ OS << "[#" << C.Text << "#]";
+ break;
+
+ case CodeCompletionString::CK_CurrentParameter:
+ OS << "<#" << C.Text << "#>";
+ break;
+
+ default: OS << C.Text; break;
+ }
+ }
+ return OS.str();
+}
+
void
PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
unsigned CurrentArg,
@@ -491,8 +515,9 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
for (unsigned I = 0; I != NumCandidates; ++I) {
if (CodeCompletionString *CCS
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
- getAllocator(), CCTUInfo)) {
- OS << "OVERLOAD: " << CCS->getAsString() << "\n";
+ getAllocator(), CCTUInfo,
+ includeBriefComments())) {
+ OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 349bb32..ea3872f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -893,18 +893,16 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
-void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
- unsigned NP,
- SourceLocation *ProtoLocs,
- SourceLocation LAngleLoc) {
- if (NP == 0) return;
- Decl **ProtoQuals = new Decl*[NP];
- memcpy(ProtoQuals, Protos, sizeof(Decl*)*NP);
- ProtocolQualifiers = ProtoQuals;
- ProtocolLocs = new SourceLocation[NP];
- memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
- NumProtocolQualifiers = NP;
- ProtocolLAngleLoc = LAngleLoc;
+bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (Concept_specified) {
+ DiagID = diag::ext_duplicate_declspec;
+ PrevSpec = "concept";
+ return true;
+ }
+ Concept_specified = true;
+ ConceptLoc = Loc;
+ return false;
}
void DeclSpec::SaveWrittenBuiltinSpecs() {
@@ -983,11 +981,18 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
getSpecifierName((TST)TypeSpecType, Policy));
}
- // Only 'short' is valid with vector bool. (PIM 2.1)
- if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
+ // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
+ if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
+ (TypeSpecWidth != TSW_longlong))
Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSW)TypeSpecWidth);
+ // vector bool long long requires VSX support.
+ if ((TypeSpecWidth == TSW_longlong) &&
+ (!PP.getTargetInfo().hasFeature("vsx")) &&
+ (!PP.getTargetInfo().hasFeature("power8-vector")))
+ Diag(D, TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
+
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
(TypeSpecWidth != TSW_unspecified))
@@ -1214,7 +1219,10 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
const char *&PrevSpec) {
+ if (!FirstLocation.isValid())
+ FirstLocation = Loc;
LastLocation = Loc;
+ LastSpecifier = VS;
if (Specifiers & VS) {
PrevSpec = getSpecifierName(VS);
diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
index 664a6b1..ceea04f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -35,6 +35,8 @@ DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD,
case Sema::AD_Unavailable:
DD.Kind = Unavailable;
break;
+ case Sema::AD_Partial:
+ llvm_unreachable("AD_Partial diags should not be delayed");
}
DD.Triggered = false;
DD.Loc = Loc;
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index 6586fb3..53263ba 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -98,7 +98,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
bool AllowInlineNamespace) const {
Ctx = Ctx->getRedeclContext();
- if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
+ if (Ctx->isFunctionOrMethod() || (S && S->isFunctionPrototypeScope())) {
// Ignore the scopes associated within transparent declaration contexts.
while (S->getEntity() && S->getEntity()->isTransparentContext())
S = S->getParent();
@@ -266,6 +266,11 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
// If the declarations are redeclarations of each other, keep the newest one.
if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
+ // If we're adding an imported declaration, don't replace another imported
+ // declaration.
+ if (Existing->isFromASTFile() && New->isFromASTFile())
+ return DMK_Different;
+
// If either of these is the most recent declaration, use it.
Decl *MostRecent = Existing->getMostRecentDecl();
if (Existing == MostRecent)
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index fd75c02..775fe85 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -72,10 +72,10 @@ public:
JumpScopeChecker(Stmt *Body, Sema &S);
private:
void BuildScopeInformation(Decl *D, unsigned &ParentScope);
- void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl,
+ void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl,
unsigned &ParentScope);
void BuildScopeInformation(Stmt *S, unsigned &origParentScope);
-
+
void VerifyJumps();
void VerifyIndirectJumps();
void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
@@ -166,7 +166,7 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
// A program that jumps from a point where a variable with automatic
// storage duration is not in scope to a point where it is in scope
// is ill-formed unless the variable has scalar type, class type with
- // a trivial default constructor and a trivial destructor, a
+ // a trivial default constructor and a trivial destructor, a
// cv-qualified version of one of these types, or an array of one of
// the preceding types and is declared without an initializer.
@@ -218,7 +218,7 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
D->getLocation()));
ParentScope = Scopes.size()-1;
}
-
+
// If the decl has an initializer, walk it with the potentially new
// scope we just installed.
if (VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -227,8 +227,8 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
}
/// \brief Build scope information for a captured block literal variables.
-void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
- const BlockDecl *BDecl,
+void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
+ const BlockDecl *BDecl,
unsigned &ParentScope) {
// exclude captured __block variables; there's no destructor
// associated with the block literal for them.
@@ -257,7 +257,7 @@ void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
SourceLocation Loc = D->getLocation();
if (Loc.isInvalid())
Loc = BDecl->getLocation();
- Scopes.push_back(GotoScope(ParentScope,
+ Scopes.push_back(GotoScope(ParentScope,
Diags.first, Diags.second, Loc));
ParentScope = Scopes.size()-1;
}
@@ -272,11 +272,11 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
// propagate out into the enclosing scope. Otherwise we have to worry
// about block literals, which have the lifetime of their enclosing statement.
unsigned independentParentScope = origParentScope;
- unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S))
+ unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S))
? origParentScope : independentParentScope);
bool SkipFirstSubStmt = false;
-
+
// If we found a label, remember that it is in ParentScope scope.
switch (S->getStmtClass()) {
case Stmt::AddrLabelExprClass:
@@ -307,7 +307,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
SkipFirstSubStmt = true;
}
// Fall through
-
+
case Stmt::GotoStmtClass:
// Remember both what scope a goto is in as well as the fact that we have
// it. This makes the second scan not have to walk the AST again.
@@ -332,9 +332,39 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
diag::note_protected_by_cxx_catch,
diag::note_exits_cxx_catch,
CS->getSourceRange().getBegin()));
- BuildScopeInformation(CS->getHandlerBlock(),
+ BuildScopeInformation(CS->getHandlerBlock(),
+ (newParentScope = Scopes.size()-1));
+ }
+ return;
+ }
+
+ case Stmt::SEHTryStmtClass: {
+ SEHTryStmt *TS = cast<SEHTryStmt>(S);
+ unsigned newParentScope;
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_try,
+ diag::note_exits_seh_try,
+ TS->getSourceRange().getBegin()));
+ if (Stmt *TryBlock = TS->getTryBlock())
+ BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1));
+
+ // Jump from __except or __finally into the __try are not allowed either.
+ if (SEHExceptStmt *Except = TS->getExceptHandler()) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_except,
+ diag::note_exits_seh_except,
+ Except->getSourceRange().getBegin()));
+ BuildScopeInformation(Except->getBlock(),
+ (newParentScope = Scopes.size()-1));
+ } else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_finally,
+ diag::note_exits_seh_finally,
+ Finally->getSourceRange().getBegin()));
+ BuildScopeInformation(Finally->getBlock(),
(newParentScope = Scopes.size()-1));
}
+
return;
}
@@ -342,13 +372,12 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
break;
}
- for (Stmt::child_range CI = S->children(); CI; ++CI) {
+ for (Stmt *SubStmt : S->children()) {
if (SkipFirstSubStmt) {
SkipFirstSubStmt = false;
continue;
}
-
- Stmt *SubStmt = *CI;
+
if (!SubStmt) continue;
// Cases, labels, and defaults aren't "scope parents". It's also
@@ -398,7 +427,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
diag::note_exits_objc_catch,
AC->getAtCatchLoc()));
// @catches are nested and it isn't
- BuildScopeInformation(AC->getCatchBody(),
+ BuildScopeInformation(AC->getCatchBody(),
(newParentScope = Scopes.size()-1));
}
@@ -413,11 +442,12 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
continue;
}
-
+
unsigned newParentScope;
// Disallow jumps into the protected statement of an @synchronized, but
// allow jumps into the object expression it protects.
- if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
+ if (ObjCAtSynchronizedStmt *AS =
+ dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)) {
// Recursively walk the AST for the @synchronized object expr, it is
// evaluated in the normal scope.
BuildScopeInformation(AS->getSynchExpr(), ParentScope);
@@ -428,20 +458,22 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
diag::note_protected_by_objc_synchronized,
diag::note_exits_objc_synchronized,
AS->getAtSynchronizedLoc()));
- BuildScopeInformation(AS->getSynchBody(),
+ BuildScopeInformation(AS->getSynchBody(),
(newParentScope = Scopes.size()-1));
continue;
}
// Disallow jumps into the protected statement of an @autoreleasepool.
- if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){
- // Recursively walk the AST for the @autoreleasepool part, protected by a new
- // scope.
+ if (ObjCAutoreleasePoolStmt *AS =
+ dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)) {
+ // Recursively walk the AST for the @autoreleasepool part, protected by a
+ // new scope.
Scopes.push_back(GotoScope(ParentScope,
diag::note_protected_by_objc_autoreleasepool,
diag::note_exits_objc_autoreleasepool,
AS->getAtLoc()));
- BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1));
+ BuildScopeInformation(AS->getSubStmt(),
+ (newParentScope = Scopes.size() - 1));
continue;
}
@@ -756,6 +788,18 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
// Common case: exactly the same scope, which is fine.
if (FromScope == ToScope) return;
+ // Warn on gotos out of __finally blocks.
+ if (isa<GotoStmt>(From) || isa<IndirectGotoStmt>(From)) {
+ // If FromScope > ToScope, FromScope is more nested and the jump goes to a
+ // less nested scope. Check if it crosses a __finally along the way.
+ for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) {
+ if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
+ S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally);
+ break;
+ }
+ }
+ }
+
unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);
// It's okay to jump out from a nested scope.
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 449ddf4..9ecb5a7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -86,6 +86,14 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
return nullptr;
}
+CXXCtorInitializer **
+MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ for (auto *S : Sources)
+ if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
+ return R;
+ return nullptr;
+}
+
bool MultiplexExternalSemaSource::
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
bool AnyDeclsFound = false;
@@ -204,7 +212,15 @@ void MultiplexExternalSemaSource::ReadUndefinedButUsed(
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUndefinedButUsed(Undefined);
}
-
+
+void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions(
+ llvm::MapVector<FieldDecl *,
+ llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) {
+ for (auto &Source : Sources)
+ Source->ReadMismatchingDeleteExpressions(Exprs);
+}
+
bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->LookupUnqualified(R, S);
@@ -236,24 +252,12 @@ void MultiplexExternalSemaSource::ReadExtVectorDecls(
Sources[i]->ReadExtVectorDecls(Decls);
}
-void MultiplexExternalSemaSource::ReadDynamicClasses(
- SmallVectorImpl<CXXRecordDecl*> &Decls) {
- for(size_t i = 0; i < Sources.size(); ++i)
- Sources[i]->ReadDynamicClasses(Decls);
-}
-
void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls);
}
-void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls(
- SmallVectorImpl<NamedDecl*> &Decls) {
- for(size_t i = 0; i < Sources.size(); ++i)
- Sources[i]->ReadLocallyScopedExternCDecls(Decls);
-}
-
void MultiplexExternalSemaSource::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
for(size_t i = 0; i < Sources.size(); ++i)
@@ -280,7 +284,7 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
}
void MultiplexExternalSemaSource::ReadLateParsedTemplates(
- llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
for (size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadLateParsedTemplates(LPTMap);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
index 6c79778..7c70048 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
@@ -38,7 +38,8 @@ void Scope::Init(Scope *parent, unsigned flags) {
FnParent = parent->FnParent;
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
- MSLocalManglingParent = parent->MSLocalManglingParent;
+ MSLastManglingParent = parent->MSLastManglingParent;
+ MSCurManglingNumber = getMSLastManglingNumber();
if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
0)
@@ -47,9 +48,10 @@ void Scope::Init(Scope *parent, unsigned flags) {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- MSLocalManglingParent = FnParent = BlockParent = nullptr;
+ MSLastManglingParent = FnParent = BlockParent = nullptr;
TemplateParamParent = nullptr;
- MSLocalManglingNumber = 1;
+ MSLastManglingNumber = 1;
+ MSCurManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
@@ -57,8 +59,9 @@ void Scope::Init(Scope *parent, unsigned flags) {
// The MS mangler uses the number of scopes that can hold declarations as
// part of an external name.
if (Flags & (ClassScope | FnScope)) {
- MSLocalManglingNumber = getMSLocalManglingNumber();
- MSLocalManglingParent = this;
+ MSLastManglingNumber = getMSLastManglingNumber();
+ MSLastManglingParent = this;
+ MSCurManglingNumber = 1;
}
if (flags & BreakScope) BreakParent = this;
if (flags & ContinueScope) ContinueParent = this;
@@ -78,7 +81,7 @@ void Scope::Init(Scope *parent, unsigned flags) {
else if ((flags & EnumScope))
; // Don't increment for enum scopes.
else
- incrementMSLocalManglingNumber();
+ incrementMSManglingNumber();
}
DeclsInScope.clear();
@@ -185,6 +188,9 @@ void Scope::dumpImpl(raw_ostream &OS) const {
} else if (Flags & SEHTryScope) {
OS << "SEHTryScope";
Flags &= ~SEHTryScope;
+ } else if (Flags & SEHExceptScope) {
+ OS << "SEHExceptScope";
+ Flags &= ~SEHExceptScope;
} else if (Flags & OpenMPDirectiveScope) {
OS << "OpenMPDirectiveScope";
Flags &= ~OpenMPDirectiveScope;
@@ -206,12 +212,13 @@ void Scope::dumpImpl(raw_ostream &OS) const {
OS << "Parent: (clang::Scope*)" << Parent << '\n';
OS << "Depth: " << Depth << '\n';
- OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
+ OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
+ OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
if (const DeclContext *DC = getEntity())
OS << "Entity : (clang::DeclContext*)" << DC << '\n';
if (NRVO.getInt())
- OS << "NRVO not allowed";
+ OS << "NRVO not allowed\n";
else if (NRVO.getPointer())
OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index 63ef3b2..f80eadf 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() {
ObjCWarnForNoDesignatedInitChain = false;
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
+ FirstCXXTryLoc = SourceLocation();
+ FirstSEHTryLoc = SourceLocation();
SwitchStack.clear();
Returns.clear();
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index b9aaf16..18d7e9d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -91,18 +91,20 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
- NSNumberDecl(nullptr),
+ NSNumberDecl(nullptr), NSValueDecl(nullptr),
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
+ ValueWithBytesObjCTypeMethod(nullptr),
NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
MSAsmLabelNameCounter(0),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
+ CachedFakeTopLevelModule(nullptr),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
- TyposCorrected(0), AnalysisWarnings(*this),
+ TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
VarDataSharingAttributesStack(nullptr), CurScope(nullptr),
Ident_super(nullptr), Ident___float128(nullptr)
{
@@ -122,9 +124,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&Context);
- ExprEvalContexts.push_back(
- ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0,
- false, nullptr, false));
+ ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false);
FunctionScopes.push_back(new FunctionScopeInfo(Diags));
@@ -195,8 +195,9 @@ void Sema::Initialize() {
}
// Initialize Microsoft "predefined C++ types".
- if (PP.getLangOpts().MSVCCompat && PP.getLangOpts().CPlusPlus) {
- if (IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
+ if (PP.getLangOpts().MSVCCompat) {
+ if (PP.getLangOpts().CPlusPlus &&
+ IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
TUScope);
@@ -213,6 +214,29 @@ void Sema::Initialize() {
addImplicitTypedef("image3d_t", Context.OCLImage3dTy);
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
+ if (getLangOpts().OpenCLVersion >= 200) {
+ addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
+ addImplicitTypedef("atomic_uint",
+ Context.getAtomicType(Context.UnsignedIntTy));
+ addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy));
+ addImplicitTypedef("atomic_ulong",
+ Context.getAtomicType(Context.UnsignedLongTy));
+ addImplicitTypedef("atomic_float",
+ Context.getAtomicType(Context.FloatTy));
+ addImplicitTypedef("atomic_double",
+ Context.getAtomicType(Context.DoubleTy));
+ // OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
+ // 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
+ addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
+ addImplicitTypedef("atomic_intptr_t",
+ Context.getAtomicType(Context.getIntPtrType()));
+ addImplicitTypedef("atomic_uintptr_t",
+ Context.getAtomicType(Context.getUIntPtrType()));
+ addImplicitTypedef("atomic_size_t",
+ Context.getAtomicType(Context.getSizeType()));
+ addImplicitTypedef("atomic_ptrdiff_t",
+ Context.getAtomicType(Context.getPointerDiffType()));
+ }
}
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
@@ -243,6 +267,8 @@ Sema::~Sema() {
if (isMultiplexExternalSource)
delete ExternalSource;
+ threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);
+
// Destroys data sharing attributes stack for OpenMP
DestroyDataSharingAttributesStack();
@@ -331,24 +357,25 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
#endif
+ // Check whether we're implicitly casting from a nullable type to a nonnull
+ // type.
+ if (auto exprNullability = E->getType()->getNullability(Context)) {
+ if (*exprNullability == NullabilityKind::Nullable) {
+ if (auto typeNullability = Ty->getNullability(Context)) {
+ if (*typeNullability == NullabilityKind::NonNull) {
+ Diag(E->getLocStart(), diag::warn_nullability_lost)
+ << E->getType() << Ty;
+ }
+ }
+ }
+ }
+
QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
if (ExprTy == TypeTy)
return E;
- // If this is a derived-to-base cast to a through a virtual base, we
- // need a vtable.
- if (Kind == CK_DerivedToBase &&
- BasePathInvolvesVirtualBase(*BasePath)) {
- QualType T = E->getType();
- if (const PointerType *Pointer = T->getAs<PointerType>())
- T = Pointer->getPointeeType();
- if (const RecordType *RecordTy = T->getAs<RecordType>())
- MarkVTableUsed(E->getLocStart(),
- cast<CXXRecordDecl>(RecordTy->getDecl()));
- }
-
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
@@ -512,14 +539,8 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
- for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) {
- llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator Pos
- = WeakUndeclaredIdentifiers.find(WeakIDs[I].first);
- if (Pos != WeakUndeclaredIdentifiers.end())
- continue;
-
- WeakUndeclaredIdentifiers.insert(WeakIDs[I]);
- }
+ for (auto &WeakID : WeakIDs)
+ WeakUndeclaredIdentifiers.insert(WeakID);
}
@@ -544,10 +565,10 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I))
Complete = M->isDefined() || (M->isPure() && !isa<CXXDestructorDecl>(M));
else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
- // If the template function is marked as late template parsed at this point,
- // it has not been instantiated and therefore we have not performed semantic
- // analysis on it yet, so we cannot know if the type can be considered
- // complete.
+ // If the template function is marked as late template parsed at this
+ // point, it has not been instantiated and therefore we have not
+ // performed semantic analysis on it yet, so we cannot know if the type
+ // can be considered complete.
Complete = !F->getTemplatedDecl()->isLateTemplateParsed() &&
F->getTemplatedDecl()->isDefined();
else if (const CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(*I)) {
@@ -632,22 +653,6 @@ void Sema::ActOnEndOfTranslationUnit() {
if (TUKind != TU_Prefix) {
DiagnoseUseOfUnimplementedSelectors();
- // If any dynamic classes have their key function defined within
- // this translation unit, then those vtables are considered "used" and must
- // be emitted.
- for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource),
- E = DynamicClasses.end();
- I != E; ++I) {
- assert(!(*I)->isDependentType() &&
- "Should not see dependent types here!");
- if (const CXXMethodDecl *KeyFunction =
- Context.getCurrentKeyFunction(*I)) {
- const FunctionDecl *Definition = nullptr;
- if (KeyFunction->hasBody(Definition))
- MarkVTableUsed(Definition->getLocation(), *I, true);
- }
- }
-
// If DefinedUsedVTables ends up marking any virtual member functions it
// might lead to more pending template instantiations, which we then need
// to instantiate.
@@ -679,6 +684,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
+ // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to
+ // write out the lists to the AST file (if any).
assert(DelayedDefaultedMemberExceptionSpecs.empty());
assert(DelayedExceptionSpecChecks.empty());
@@ -696,16 +703,13 @@ void Sema::ActOnEndOfTranslationUnit() {
}
// Check for #pragma weak identifiers that were never declared
- // FIXME: This will cause diagnostics to be emitted in a non-determinstic
- // order! Iterating over a densemap like this is bad.
LoadExternalWeakUndeclaredIdentifiers();
- for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
- I = WeakUndeclaredIdentifiers.begin(),
- E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
- if (I->second.getUsed()) continue;
+ for (auto WeakID : WeakUndeclaredIdentifiers) {
+ if (WeakID.second.getUsed())
+ continue;
- Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
- << I->first;
+ Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
+ << WeakID.first;
}
if (LangOpts.CPlusPlus11 &&
@@ -732,11 +736,7 @@ void Sema::ActOnEndOfTranslationUnit() {
ModMap.resolveConflicts(Mod, /*Complain=*/false);
// Queue the submodules, so their exports will also be resolved.
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
- Sub != SubEnd; ++Sub) {
- Stack.push_back(*Sub);
- }
+ Stack.append(Mod->submodule_begin(), Mod->submodule_end());
}
}
@@ -871,6 +871,17 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
+ if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) {
+ if (ExternalSource)
+ ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs);
+ for (const auto &DeletedFieldInfo : DeleteExprs) {
+ for (const auto &DeleteExprLoc : DeletedFieldInfo.second) {
+ AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first,
+ DeleteExprLoc.second);
+ }
+ }
+ }
+
// Check we've noticed that we're no longer parsing the initializer for every
// variable. If we miss cases, then at best we have a performance issue and
// at worst a rejects-valid bug.
@@ -1230,6 +1241,9 @@ void ExternalSemaSource::ReadUndefinedButUsed(
llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) {
}
+void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
+
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
SourceLocation Loc = this->Loc;
if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
@@ -1478,3 +1492,8 @@ CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
}
+
+const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
+Sema::getMismatchingDeleteExpressions() const {
+ return DeleteExprs;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 37240c2..0e973cc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -1462,7 +1462,7 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
case AR_inaccessible: return Sema::AR_inaccessible;
case AR_dependent: return Sema::AR_dependent;
}
- llvm_unreachable("falling off end");
+ llvm_unreachable("invalid access result");
}
void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 7629797..5a29bad 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -131,7 +131,7 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
if (MSStructPragmaOn)
- RD->addAttr(MsStructAttr::CreateImplicit(Context));
+ RD->addAttr(MSStructAttr::CreateImplicit(Context));
// FIXME: We should merge AddAlignmentAttributesForRecord with
// AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
@@ -422,6 +422,9 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
if (Action & PSK_Pop && Stack->Stack.empty())
Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
<< "stack empty";
+ if (SegmentName &&
+ !checkSectionName(SegmentName->getLocStart(), SegmentName->getString()))
+ return;
Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
index 64222fb..5973500 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
@@ -62,6 +62,11 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
const FunctionDecl *Callee) {
+ // The CUDADisableTargetCallChecks short-circuits this check: we assume all
+ // cross-target calls are valid.
+ if (getLangOpts().CUDADisableTargetCallChecks)
+ return false;
+
CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
CalleeTarget = IdentifyCUDATarget(Callee);
@@ -92,9 +97,21 @@ bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
if (Caller->isImplicit()) return false;
bool InDeviceMode = getLangOpts().CUDAIsDevice;
- if ((InDeviceMode && CalleeTarget != CFT_Device) ||
- (!InDeviceMode && CalleeTarget != CFT_Host))
+ if (!InDeviceMode && CalleeTarget != CFT_Host)
+ return true;
+ if (InDeviceMode && CalleeTarget != CFT_Device) {
+ // Allow host device functions to call host functions if explicitly
+ // requested.
+ if (CalleeTarget == CFT_Host &&
+ getLangOpts().CUDAAllowHostCallsFromHostDevice) {
+ Diag(Caller->getLocation(),
+ diag::warn_host_calls_from_host_device)
+ << Callee->getNameAsString() << Caller->getNameAsString();
+ return false;
+ }
+
return true;
+ }
}
return false;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 3e56e67..9e146ed 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -218,6 +218,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
// Fixed enum types are complete, but they aren't valid as scopes
// until we see a definition, so awkwardly pull out this special
// case.
+ // FIXME: The definition might not be visible; complain if it is not.
const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
if (!enumType || enumType->getDecl()->isCompleteDefinition())
return false;
@@ -282,7 +283,11 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
/// \brief Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
-bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
+/// \param SD Declaration checked for nested-name-specifier.
+/// \param IsExtension If not null and the declaration is accepted as an
+/// extension, the pointed variable is assigned true.
+bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+ bool *IsExtension) {
if (!SD)
return false;
@@ -298,14 +303,23 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
if (T->isDependentType())
return true;
- else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
- if (TD->getUnderlyingType()->isRecordType() ||
- (Context.getLangOpts().CPlusPlus11 &&
- TD->getUnderlyingType()->isEnumeralType()))
+ if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
+ if (TD->getUnderlyingType()->isRecordType())
return true;
- } else if (isa<RecordDecl>(SD) ||
- (Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD)))
+ if (TD->getUnderlyingType()->isEnumeralType()) {
+ if (Context.getLangOpts().CPlusPlus11)
+ return true;
+ if (IsExtension)
+ *IsExtension = true;
+ }
+ } else if (isa<RecordDecl>(SD)) {
return true;
+ } else if (isa<EnumDecl>(SD)) {
+ if (Context.getLangOpts().CPlusPlus11)
+ return true;
+ if (IsExtension)
+ *IsExtension = true;
+ }
return false;
}
@@ -599,7 +613,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
- if (isAcceptableNestedNameSpecifier(SD)) {
+ bool IsExtension = false;
+ bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension);
+ if (!AcceptSpec && IsExtension) {
+ AcceptSpec = true;
+ Diag(IdentifierLoc, diag::ext_nested_name_spec_is_enum);
+ }
+ if (AcceptSpec) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope &&
!getLangOpts().CPlusPlus11) {
// C++03 [basic.lookup.classref]p4:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index a4c2d9b..c0754ba 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -389,6 +389,33 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
S.Diag(opRange.getBegin(), msg) << castType
<< src->getType() << destType << opRange << src->getSourceRange();
+
+ // Detect if both types are (ptr to) class, and note any incompleteness.
+ int DifferentPtrness = 0;
+ QualType From = destType;
+ if (auto Ptr = From->getAs<PointerType>()) {
+ From = Ptr->getPointeeType();
+ DifferentPtrness++;
+ }
+ QualType To = src->getType();
+ if (auto Ptr = To->getAs<PointerType>()) {
+ To = Ptr->getPointeeType();
+ DifferentPtrness--;
+ }
+ if (!DifferentPtrness) {
+ auto RecFrom = From->getAs<RecordType>();
+ auto RecTo = To->getAs<RecordType>();
+ if (RecFrom && RecTo) {
+ auto DeclFrom = RecFrom->getAsCXXRecordDecl();
+ if (!DeclFrom->isCompleteDefinition())
+ S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete)
+ << DeclFrom->getDeclName();
+ auto DeclTo = RecTo->getAsCXXRecordDecl();
+ if (!DeclTo->isCompleteDefinition())
+ S.Diag(DeclTo->getLocation(), diag::note_type_incomplete)
+ << DeclTo->getDeclName();
+ }
+ }
}
/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
@@ -665,12 +692,6 @@ void CastOperation::CheckDynamicCast() {
}
Kind = CK_DerivedToBase;
-
- // If we are casting to or through a virtual base class, we need a
- // vtable.
- if (Self.BasePathInvolvesVirtualBase(BasePath))
- Self.MarkVTableUsed(OpRange.getBegin(),
- cast<CXXRecordDecl>(SrcRecord->getDecl()));
return;
}
@@ -682,8 +703,6 @@ void CastOperation::CheckDynamicCast() {
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
}
- Self.MarkVTableUsed(OpRange.getBegin(),
- cast<CXXRecordDecl>(SrcRecord->getDecl()));
// dynamic_cast is not available with -fno-rtti.
// As an exception, dynamic_cast to void* is available because it doesn't
@@ -956,7 +975,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
if (tcr != TC_NotApplicable)
return tcr;
- // C++0x [expr.static.cast]p3:
+ // C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
@@ -1062,6 +1081,15 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
Kind = CK_BitCast;
return TC_Success;
}
+
+ // Microsoft permits static_cast from 'pointer-to-void' to
+ // 'pointer-to-function'.
+ if (!CStyle && Self.getLangOpts().MSVCCompat &&
+ DestPointee->isFunctionType()) {
+ Self.Diag(OpRange.getBegin(), diag::ext_ms_cast_fn_obj) << OpRange;
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
}
else if (DestType->isObjCObjectPointerType()) {
// allow both c-style cast and static_cast of objective-c pointers as
@@ -1087,6 +1115,14 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
if (!CStyle &&
Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind))
return TC_Success;
+
+ // See if it looks like the user is trying to convert between
+ // related record types, and select a better diagnostic if so.
+ if (auto SrcPointer = SrcType->getAs<PointerType>())
+ if (auto DestPointer = DestType->getAs<PointerType>())
+ if (SrcPointer->getPointeeType()->getAs<RecordType>() &&
+ DestPointer->getPointeeType()->getAs<RecordType>())
+ msg = diag::err_bad_cxx_cast_unrelated_class;
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
@@ -1097,7 +1133,7 @@ TryCastResult
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
unsigned &msg) {
- // C++0x [expr.static.cast]p3:
+ // C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
@@ -1125,6 +1161,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
DerivedToBase, ObjCConversion,
ObjCLifetimeConversion)
< Sema::Ref_Compatible_With_Added_Qualification) {
+ if (CStyle)
+ return TC_NotApplicable;
msg = diag::err_bad_lvalue_to_rvalue_cast;
return TC_Failed;
}
@@ -1790,8 +1828,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// can be explicitly converted to an rvalue of type "pointer to member
// of Y of type T2" if T1 and T2 are both function types or both object
// types.
- if (DestMemPtr->getPointeeType()->isFunctionType() !=
- SrcMemPtr->getPointeeType()->isFunctionType())
+ if (DestMemPtr->isMemberFunctionPointer() !=
+ SrcMemPtr->isMemberFunctionPointer())
return TC_NotApplicable;
// C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 6ab957e..d9d26e2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -184,7 +184,7 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
return true;
}
- QualType ReturnTy = CE->getCallReturnType();
+ QualType ReturnTy = CE->getCallReturnType(S.Context);
QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() };
QualType BuiltinTy = S.Context.getFunctionType(
ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo());
@@ -202,6 +202,28 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
return false;
}
+static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
+ Scope::ScopeFlags NeededScopeFlags,
+ unsigned DiagID) {
+ // Scopes aren't available during instantiation. Fortunately, builtin
+ // functions cannot be template args so they cannot be formed through template
+ // instantiation. Therefore checking once during the parse is sufficient.
+ if (!SemaRef.ActiveTemplateInstantiations.empty())
+ return false;
+
+ Scope *S = SemaRef.getCurScope();
+ while (S && !S->isSEHExceptScope())
+ S = S->getParent();
+ if (!S || !(S->getFlags() & NeededScopeFlags)) {
+ auto *DRE = cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ SemaRef.Diag(TheCall->getExprLoc(), DiagID)
+ << DRE->getDecl()->getIdentifier();
+ return true;
+ }
+
+ return false;
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
CallExpr *TheCall) {
@@ -301,6 +323,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinSetjmp(TheCall))
return ExprError();
break;
+ case Builtin::BI_setjmp:
+ case Builtin::BI_setjmpex:
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+ break;
case Builtin::BI__builtin_classify_type:
if (checkArgCount(*this, TheCall, 1)) return true;
@@ -465,6 +492,35 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinCallWithStaticChain(*this, TheCall))
return ExprError();
break;
+
+ case Builtin::BI__exception_code:
+ case Builtin::BI_exception_code: {
+ if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope,
+ diag::err_seh___except_block))
+ return ExprError();
+ break;
+ }
+ case Builtin::BI__exception_info:
+ case Builtin::BI_exception_info: {
+ if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope,
+ diag::err_seh___except_filter))
+ return ExprError();
+ break;
+ }
+
+ case Builtin::BI__GetExceptionInfo:
+ if (checkArgCount(*this, TheCall, 1))
+ return ExprError();
+
+ if (CheckCXXThrowOperand(
+ TheCall->getLocStart(),
+ Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()),
+ TheCall))
+ return ExprError();
+
+ TheCall->setType(Context.VoidPtrTy);
+ break;
+
}
// Since the target specific builtins for each arch overlap, only check those
@@ -490,11 +546,21 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::systemz:
+ if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
default:
break;
}
@@ -557,7 +623,10 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
case NeonTypeFlags::Poly16:
return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
case NeonTypeFlags::Poly64:
- return Context.UnsignedLongTy;
+ if (IsInt64Long)
+ return Context.UnsignedLongTy;
+ else
+ return Context.UnsignedLongLongTy;
case NeonTypeFlags::Poly128:
break;
case NeonTypeFlags::Float16:
@@ -767,6 +836,16 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
SemaBuiltinConstantArgRange(TheCall, 2, 0, 1);
}
+ if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
+
+ if (BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -807,6 +886,16 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
SemaBuiltinConstantArgRange(TheCall, 4, 0, 1);
}
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, false);
+
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -839,15 +928,163 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
+bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ unsigned i = 0, l = 0, u = 0;
+ bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde ||
+ BuiltinID == PPC::BI__builtin_divdeu ||
+ BuiltinID == PPC::BI__builtin_bpermd;
+ bool IsTarget64Bit = Context.getTargetInfo()
+ .getTypeWidth(Context
+ .getTargetInfo()
+ .getIntPtrType()) == 64;
+ bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe ||
+ BuiltinID == PPC::BI__builtin_divweu ||
+ BuiltinID == PPC::BI__builtin_divde ||
+ BuiltinID == PPC::BI__builtin_divdeu;
+
+ if (Is64BitBltin && !IsTarget64Bit)
+ return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt)
+ << TheCall->getSourceRange();
+
+ if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) ||
+ (BuiltinID == PPC::BI__builtin_bpermd &&
+ !Context.getTargetInfo().hasFeature("bpermd")))
+ return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7)
+ << TheCall->getSourceRange();
+
+ switch (BuiltinID) {
+ default: return false;
+ case PPC::BI__builtin_altivec_crypto_vshasigmaw:
+ case PPC::BI__builtin_altivec_crypto_vshasigmad:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 15);
+ case PPC::BI__builtin_tbegin:
+ case PPC::BI__builtin_tend: i = 0; l = 0; u = 1; break;
+ case PPC::BI__builtin_tsr: i = 0; l = 0; u = 7; break;
+ case PPC::BI__builtin_tabortwc:
+ case PPC::BI__builtin_tabortdc: i = 0; l = 0; u = 31; break;
+ case PPC::BI__builtin_tabortwci:
+ case PPC::BI__builtin_tabortdci:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
+ }
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+}
+
+bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ if (BuiltinID == SystemZ::BI__builtin_tabort) {
+ Expr *Arg = TheCall->getArg(0);
+ llvm::APSInt AbortCode(32);
+ if (Arg->isIntegerConstantExpr(AbortCode, Context) &&
+ AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256)
+ return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code)
+ << Arg->getSourceRange();
+ }
+
+ // For intrinsics which take an immediate value as part of the instruction,
+ // range check them here.
+ unsigned i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default: return false;
+ case SystemZ::BI__builtin_s390_lcbb: i = 1; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_verimb:
+ case SystemZ::BI__builtin_s390_verimh:
+ case SystemZ::BI__builtin_s390_verimf:
+ case SystemZ::BI__builtin_s390_verimg: i = 3; l = 0; u = 255; break;
+ case SystemZ::BI__builtin_s390_vfaeb:
+ case SystemZ::BI__builtin_s390_vfaeh:
+ case SystemZ::BI__builtin_s390_vfaef:
+ case SystemZ::BI__builtin_s390_vfaebs:
+ case SystemZ::BI__builtin_s390_vfaehs:
+ case SystemZ::BI__builtin_s390_vfaefs:
+ case SystemZ::BI__builtin_s390_vfaezb:
+ case SystemZ::BI__builtin_s390_vfaezh:
+ case SystemZ::BI__builtin_s390_vfaezf:
+ case SystemZ::BI__builtin_s390_vfaezbs:
+ case SystemZ::BI__builtin_s390_vfaezhs:
+ case SystemZ::BI__builtin_s390_vfaezfs: i = 2; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vfidb:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 15);
+ case SystemZ::BI__builtin_s390_vftcidb: i = 1; l = 0; u = 4095; break;
+ case SystemZ::BI__builtin_s390_vlbb: i = 1; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vpdi: i = 2; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vsldb: i = 2; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vstrcb:
+ case SystemZ::BI__builtin_s390_vstrch:
+ case SystemZ::BI__builtin_s390_vstrcf:
+ case SystemZ::BI__builtin_s390_vstrczb:
+ case SystemZ::BI__builtin_s390_vstrczh:
+ case SystemZ::BI__builtin_s390_vstrczf:
+ case SystemZ::BI__builtin_s390_vstrcbs:
+ case SystemZ::BI__builtin_s390_vstrchs:
+ case SystemZ::BI__builtin_s390_vstrcfs:
+ case SystemZ::BI__builtin_s390_vstrczbs:
+ case SystemZ::BI__builtin_s390_vstrczhs:
+ case SystemZ::BI__builtin_s390_vstrczfs: i = 3; l = 0; u = 15; break;
+ }
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
+ case X86::BI__builtin_cpu_supports:
+ return SemaBuiltinCpuSupports(TheCall);
case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
+ case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break;
+ case X86::BI__builtin_ia32_vpermil2pd:
+ case X86::BI__builtin_ia32_vpermil2pd256:
+ case X86::BI__builtin_ia32_vpermil2ps:
+ case X86::BI__builtin_ia32_vpermil2ps256: i = 3, l = 0; u = 3; break;
+ case X86::BI__builtin_ia32_cmpb128_mask:
+ case X86::BI__builtin_ia32_cmpw128_mask:
+ case X86::BI__builtin_ia32_cmpd128_mask:
+ case X86::BI__builtin_ia32_cmpq128_mask:
+ case X86::BI__builtin_ia32_cmpb256_mask:
+ case X86::BI__builtin_ia32_cmpw256_mask:
+ case X86::BI__builtin_ia32_cmpd256_mask:
+ case X86::BI__builtin_ia32_cmpq256_mask:
+ case X86::BI__builtin_ia32_cmpb512_mask:
+ case X86::BI__builtin_ia32_cmpw512_mask:
+ case X86::BI__builtin_ia32_cmpd512_mask:
+ case X86::BI__builtin_ia32_cmpq512_mask:
+ case X86::BI__builtin_ia32_ucmpb128_mask:
+ case X86::BI__builtin_ia32_ucmpw128_mask:
+ case X86::BI__builtin_ia32_ucmpd128_mask:
+ case X86::BI__builtin_ia32_ucmpq128_mask:
+ case X86::BI__builtin_ia32_ucmpb256_mask:
+ case X86::BI__builtin_ia32_ucmpw256_mask:
+ case X86::BI__builtin_ia32_ucmpd256_mask:
+ case X86::BI__builtin_ia32_ucmpq256_mask:
+ case X86::BI__builtin_ia32_ucmpb512_mask:
+ case X86::BI__builtin_ia32_ucmpw512_mask:
+ case X86::BI__builtin_ia32_ucmpd512_mask:
+ case X86::BI__builtin_ia32_ucmpq512_mask: i = 2; l = 0; u = 7; break;
+ case X86::BI__builtin_ia32_roundps:
+ case X86::BI__builtin_ia32_roundpd:
+ case X86::BI__builtin_ia32_roundps256:
+ case X86::BI__builtin_ia32_roundpd256: i = 1, l = 0; u = 15; break;
+ case X86::BI__builtin_ia32_roundss:
+ case X86::BI__builtin_ia32_roundsd: i = 2, l = 0; u = 15; break;
case X86::BI__builtin_ia32_cmpps:
case X86::BI__builtin_ia32_cmpss:
case X86::BI__builtin_ia32_cmppd:
- case X86::BI__builtin_ia32_cmpsd: i = 2; l = 0; u = 31; break;
+ case X86::BI__builtin_ia32_cmpsd:
+ case X86::BI__builtin_ia32_cmpps256:
+ case X86::BI__builtin_ia32_cmppd256:
+ case X86::BI__builtin_ia32_cmpps512_mask:
+ case X86::BI__builtin_ia32_cmppd512_mask: i = 2; l = 0; u = 31; break;
+ case X86::BI__builtin_ia32_vpcomub:
+ case X86::BI__builtin_ia32_vpcomuw:
+ case X86::BI__builtin_ia32_vpcomud:
+ case X86::BI__builtin_ia32_vpcomuq:
+ case X86::BI__builtin_ia32_vpcomb:
+ case X86::BI__builtin_ia32_vpcomw:
+ case X86::BI__builtin_ia32_vpcomd:
+ case X86::BI__builtin_ia32_vpcomq: i = 2; l = 0; u = 7; break;
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
@@ -880,6 +1117,13 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// \brief Returns true if the value evaluates to null.
static bool CheckNonNullExpr(Sema &S,
const Expr *Expr) {
+ // If the expression has non-null type, it doesn't evaluate to null.
+ if (auto nullability
+ = Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) {
+ if (*nullability == NullabilityKind::NonNull)
+ return false;
+ }
+
// As a special case, transparent unions initialized with zero are
// considered null for the purposes of the nonnull attribute.
if (const RecordType *UT = Expr->getType()->getAsUnionType()) {
@@ -955,56 +1199,111 @@ DiagnoseCStringFormatDirectiveInCFAPI(Sema &S,
}
}
+/// Determine whether the given type has a non-null nullability annotation.
+static bool isNonNullType(ASTContext &ctx, QualType type) {
+ if (auto nullability = type->getNullability(ctx))
+ return *nullability == NullabilityKind::NonNull;
+
+ return false;
+}
+
static void CheckNonNullArguments(Sema &S,
const NamedDecl *FDecl,
+ const FunctionProtoType *Proto,
ArrayRef<const Expr *> Args,
SourceLocation CallSiteLoc) {
+ assert((FDecl || Proto) && "Need a function declaration or prototype");
+
// Check the attributes attached to the method/function itself.
llvm::SmallBitVector NonNullArgs;
- for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
- if (!NonNull->args_size()) {
- // Easy case: all pointer arguments are nonnull.
- for (const auto *Arg : Args)
- if (S.isValidPointerAttrType(Arg->getType()))
- CheckNonNullArgument(S, Arg, CallSiteLoc);
- return;
- }
+ if (FDecl) {
+ // Handle the nonnull attribute on the function/method declaration itself.
+ for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
+ if (!NonNull->args_size()) {
+ // Easy case: all pointer arguments are nonnull.
+ for (const auto *Arg : Args)
+ if (S.isValidPointerAttrType(Arg->getType()))
+ CheckNonNullArgument(S, Arg, CallSiteLoc);
+ return;
+ }
- for (unsigned Val : NonNull->args()) {
- if (Val >= Args.size())
- continue;
- if (NonNullArgs.empty())
- NonNullArgs.resize(Args.size());
- NonNullArgs.set(Val);
+ for (unsigned Val : NonNull->args()) {
+ if (Val >= Args.size())
+ continue;
+ if (NonNullArgs.empty())
+ NonNullArgs.resize(Args.size());
+ NonNullArgs.set(Val);
+ }
}
}
- // Check the attributes on the parameters.
- ArrayRef<ParmVarDecl*> parms;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
- parms = FD->parameters();
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl))
- parms = MD->parameters();
-
- unsigned ArgIndex = 0;
- for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
- I != E; ++I, ++ArgIndex) {
- const ParmVarDecl *PVD = *I;
- if (PVD->hasAttr<NonNullAttr>() ||
- (ArgIndex < NonNullArgs.size() && NonNullArgs[ArgIndex]))
- CheckNonNullArgument(S, Args[ArgIndex], CallSiteLoc);
+ if (FDecl && (isa<FunctionDecl>(FDecl) || isa<ObjCMethodDecl>(FDecl))) {
+ // Handle the nonnull attribute on the parameters of the
+ // function/method.
+ ArrayRef<ParmVarDecl*> parms;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
+ parms = FD->parameters();
+ else
+ parms = cast<ObjCMethodDecl>(FDecl)->parameters();
+
+ unsigned ParamIndex = 0;
+ for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
+ I != E; ++I, ++ParamIndex) {
+ const ParmVarDecl *PVD = *I;
+ if (PVD->hasAttr<NonNullAttr>() ||
+ isNonNullType(S.Context, PVD->getType())) {
+ if (NonNullArgs.empty())
+ NonNullArgs.resize(Args.size());
+
+ NonNullArgs.set(ParamIndex);
+ }
+ }
+ } else {
+ // If we have a non-function, non-method declaration but no
+ // function prototype, try to dig out the function prototype.
+ if (!Proto) {
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(FDecl)) {
+ QualType type = VD->getType().getNonReferenceType();
+ if (auto pointerType = type->getAs<PointerType>())
+ type = pointerType->getPointeeType();
+ else if (auto blockType = type->getAs<BlockPointerType>())
+ type = blockType->getPointeeType();
+ // FIXME: data member pointers?
+
+ // Dig out the function prototype, if there is one.
+ Proto = type->getAs<FunctionProtoType>();
+ }
+ }
+
+ // Fill in non-null argument information from the nullability
+ // information on the parameter types (if we have them).
+ if (Proto) {
+ unsigned Index = 0;
+ for (auto paramType : Proto->getParamTypes()) {
+ if (isNonNullType(S.Context, paramType)) {
+ if (NonNullArgs.empty())
+ NonNullArgs.resize(Args.size());
+
+ NonNullArgs.set(Index);
+ }
+
+ ++Index;
+ }
+ }
}
- // In case this is a variadic call, check any remaining arguments.
- for (/**/; ArgIndex < NonNullArgs.size(); ++ArgIndex)
+ // Check for non-null arguments.
+ for (unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
+ ArgIndex != ArgIndexEnd; ++ArgIndex) {
if (NonNullArgs[ArgIndex])
CheckNonNullArgument(S, Args[ArgIndex], CallSiteLoc);
+ }
}
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, and NULL arguments passed to non-NULL parameters.
-void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
- unsigned NumParams, bool IsMemberFunction,
+void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+ ArrayRef<const Expr *> Args, bool IsMemberFunction,
SourceLocation Loc, SourceRange Range,
VariadicCallType CallType) {
// FIXME: We should check as much as we can in the template definition.
@@ -1026,6 +1325,13 @@ void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
// Refuse POD arguments that weren't caught by the format string
// checks above.
if (CallType != VariadicDoesNotApply) {
+ unsigned NumParams = Proto ? Proto->getNumParams()
+ : FDecl && isa<FunctionDecl>(FDecl)
+ ? cast<FunctionDecl>(FDecl)->getNumParams()
+ : FDecl && isa<ObjCMethodDecl>(FDecl)
+ ? cast<ObjCMethodDecl>(FDecl)->param_size()
+ : 0;
+
for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
@@ -1035,12 +1341,14 @@ void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
}
}
- if (FDecl) {
- CheckNonNullArguments(*this, FDecl, Args, Loc);
+ if (FDecl || Proto) {
+ CheckNonNullArguments(*this, FDecl, Proto, Args, Loc);
// Type safety checking.
- for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
- CheckArgumentWithTypeTag(I, Args.data());
+ if (FDecl) {
+ for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
+ CheckArgumentWithTypeTag(I, Args.data());
+ }
}
}
@@ -1052,8 +1360,8 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl,
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Args, Proto->getNumParams(),
- /*IsMemberFunction=*/true, Loc, SourceRange(), CallType);
+ checkCall(FDecl, Proto, Args, /*IsMemberFunction=*/true, Loc, SourceRange(),
+ CallType);
}
/// CheckFunctionCall - Check a direct function call for various correctness
@@ -1066,7 +1374,6 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
IsMemberOperatorCall;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto,
TheCall->getCallee());
- unsigned NumParams = Proto ? Proto->getNumParams() : 0;
Expr** Args = TheCall->getArgs();
unsigned NumArgs = TheCall->getNumArgs();
if (IsMemberOperatorCall) {
@@ -1076,7 +1383,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
++Args;
--NumArgs;
}
- checkCall(FDecl, llvm::makeArrayRef(Args, NumArgs), NumParams,
+ checkCall(FDecl, Proto, llvm::makeArrayRef(Args, NumArgs),
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -1110,21 +1417,25 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
VariadicCallType CallType =
Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
- checkCall(Method, Args, Method->param_size(),
- /*IsMemberFunction=*/false,
- lbrac, Method->getSourceRange(), CallType);
+ checkCall(Method, nullptr, Args,
+ /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
+ CallType);
return false;
}
bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
const FunctionProtoType *Proto) {
- const VarDecl *V = dyn_cast<VarDecl>(NDecl);
- if (!V)
+ QualType Ty;
+ if (const auto *V = dyn_cast<VarDecl>(NDecl))
+ Ty = V->getType().getNonReferenceType();
+ else if (const auto *F = dyn_cast<FieldDecl>(NDecl))
+ Ty = F->getType().getNonReferenceType();
+ else
return false;
- QualType Ty = V->getType();
- if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType())
+ if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType() &&
+ !Ty->isFunctionProtoType())
return false;
VariadicCallType CallType;
@@ -1135,11 +1446,10 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
} else { // Ty->isFunctionPointerType()
CallType = VariadicFunction;
}
- unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(NDecl, llvm::makeArrayRef(TheCall->getArgs(),
- TheCall->getNumArgs()),
- NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
+ checkCall(NDecl, Proto,
+ llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
+ /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
return false;
@@ -1150,11 +1460,9 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
TheCall->getCallee());
- unsigned NumParams = Proto ? Proto->getNumParams() : 0;
-
- checkCall(/*FDecl=*/nullptr,
+ checkCall(/*FDecl=*/nullptr, Proto,
llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
- NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
+ /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
return false;
@@ -1220,9 +1528,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// M is C if C is an integer, and ptrdiff_t if C is a pointer, and
// the int parameters are for orderings.
- assert(AtomicExpr::AO__c11_atomic_init == 0 &&
- AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load
- && "need to update code for modified C11 atomics");
+ static_assert(AtomicExpr::AO__c11_atomic_init == 0 &&
+ AtomicExpr::AO__c11_atomic_fetch_xor + 1 ==
+ AtomicExpr::AO__atomic_load,
+ "need to update code for modified C11 atomics");
bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init &&
Op <= AtomicExpr::AO__c11_atomic_fetch_xor;
bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
@@ -1385,6 +1694,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
+ // atomic_fetch_or takes a pointer to a volatile 'A'. We shouldn't let the
+ // volatile-ness of the pointee-type inject itself into the result or the
+ // other operands.
+ ValType.removeLocalVolatile();
QualType ResultType = ValType;
if (Form == Copy || Form == GNUXchg || Form == Init)
ResultType = Context.VoidTy;
@@ -2039,7 +2352,7 @@ bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
if (checkBuiltinArgument(*this, Call, 0))
return true;
- static const struct {
+ const struct {
unsigned ArgNo;
QualType Type;
} ArgumentTypes[] = {
@@ -2286,7 +2599,7 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
if (Arg->isInstantiationDependent()) return false;
if (Arg->HasSideEffects(Context))
- return Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
+ Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
<< Arg->getSourceRange()
<< cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();
@@ -2370,6 +2683,127 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
return false;
}
+/// SemaBuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
+/// TheCall is an ARM/AArch64 special register string literal.
+bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+ int ArgNum, unsigned ExpectedFieldNum,
+ bool AllowName) {
+ bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp;
+ bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp;
+ assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
+
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the type of special register given.
+ StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ SmallVector<StringRef, 6> Fields;
+ Reg.split(Fields, ":");
+
+ if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
+ return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ << Arg->getSourceRange();
+
+ // If the string is the name of a register then we cannot check that it is
+ // valid here but if the string is of one the forms described in ACLE then we
+ // can check that the supplied fields are integers and within the valid
+ // ranges.
+ if (Fields.size() > 1) {
+ bool FiveFields = Fields.size() == 5;
+
+ bool ValidString = true;
+ if (IsARMBuiltin) {
+ ValidString &= Fields[0].startswith_lower("cp") ||
+ Fields[0].startswith_lower("p");
+ if (ValidString)
+ Fields[0] =
+ Fields[0].drop_front(Fields[0].startswith_lower("cp") ? 2 : 1);
+
+ ValidString &= Fields[2].startswith_lower("c");
+ if (ValidString)
+ Fields[2] = Fields[2].drop_front(1);
+
+ if (FiveFields) {
+ ValidString &= Fields[3].startswith_lower("c");
+ if (ValidString)
+ Fields[3] = Fields[3].drop_front(1);
+ }
+ }
+
+ SmallVector<int, 5> Ranges;
+ if (FiveFields)
+ Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 7, 15, 15});
+ else
+ Ranges.append({15, 7, 15});
+
+ for (unsigned i=0; i<Fields.size(); ++i) {
+ int IntField;
+ ValidString &= !Fields[i].getAsInteger(10, IntField);
+ ValidString &= (IntField >= 0 && IntField <= Ranges[i]);
+ }
+
+ if (!ValidString)
+ return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ << Arg->getSourceRange();
+
+ } else if (IsAArch64Builtin && Fields.size() == 1) {
+ // If the register name is one of those that appear in the condition below
+ // and the special register builtin being used is one of the write builtins,
+ // then we require that the argument provided for writing to the register
+ // is an integer constant expression. This is because it will be lowered to
+ // an MSR (immediate) instruction, so we need to know the immediate at
+ // compile time.
+ if (TheCall->getNumArgs() != 2)
+ return false;
+
+ std::string RegLower = Reg.lower();
+ if (RegLower != "spsel" && RegLower != "daifset" && RegLower != "daifclr" &&
+ RegLower != "pan" && RegLower != "uao")
+ return false;
+
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
+ }
+
+ return false;
+}
+
+/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
+/// This checks that the target supports __builtin_cpu_supports and
+/// that the string argument is constant and valid.
+bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the contents of the string.
+ StringRef Feature =
+ cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ if (!Context.getTargetInfo().validateCpuSupports(Feature))
+ return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
+ << Arg->getSourceRange();
+ return false;
+}
+
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -2604,6 +3038,7 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
.Case("strfmon", FST_Strfmon)
.Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
.Case("freebsd_kprintf", FST_FreeBSDKPrintf)
+ .Case("os_trace", FST_OSTrace)
.Default(FST_Unknown);
}
@@ -3074,10 +3509,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall,
if (InFunctionCall) {
const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag);
D << StringRange;
- for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end();
- I != E; ++I) {
- D << *I;
- }
+ D << FixIt;
} else {
S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag)
<< ArgumentExpr->getSourceRange();
@@ -3087,10 +3519,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall,
diag::note_format_string_defined);
Note << StringRange;
- for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end();
- I != E; ++I) {
- Note << *I;
- }
+ Note << FixIt;
}
}
@@ -3143,8 +3572,18 @@ public:
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
const Expr *E);
+
+ void HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
+
+ void HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
-};
+ void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
+ const char *flagsEnd,
+ const char *conversionPosition)
+ override;
+};
}
bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
@@ -3264,6 +3703,41 @@ void CheckPrintfHandler::HandleIgnoredFlag(
getSpecifierRange(ignoredFlag.getPosition(), 1)));
}
+// void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
+// bool IsStringLocation, Range StringRange,
+// ArrayRef<FixItHint> Fixit = None);
+
+void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an empty flag.
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_empty_objc_flag),
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ getSpecifierRange(startFlag, flagLen));
+}
+
+void CheckPrintfHandler::HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an invalid flag.
+ auto Range = getSpecifierRange(startFlag, flagLen);
+ StringRef flag(startFlag, flagLen);
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_invalid_objc_flag) << flag,
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
+void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
+ const char *flagsStart, const char *flagsEnd, const char *conversionPosition) {
+ // Warn about using '[...]' without a '@' conversion.
+ auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
+ auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
+ EmitFormatDiagnostic(S.PDiag(diag) << StringRef(conversionPosition, 1),
+ getLocationOfByte(conversionPosition),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
// Determines if the specified is a C++ class or struct containing
// a member with the specified name and kind (e.g. a CXXMethodDecl named
// "c_str()").
@@ -3600,8 +4074,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
ExprTy = TET->getUnderlyingExpr()->getType();
}
- if (AT.matchesType(S.Context, ExprTy))
+ analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy);
+
+ if (match == analyze_printf::ArgType::Match) {
return true;
+ }
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
@@ -3696,16 +4173,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
+ unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
+ if (match == analyze_format_string::ArgType::NoMatchPedantic) {
+ diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
+ }
// In this case, the specifier is wrong and should be changed to match
// the argument.
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum
- << E->getSourceRange(),
- E->getLocStart(),
- /*IsStringLocation*/false,
- SpecRange,
- FixItHint::CreateReplacement(SpecRange, os.str()));
+ EmitFormatDiagnostic(S.PDiag(diag)
+ << AT.getRepresentativeTypeName(S.Context)
+ << IntendedTy << IsEnum << E->getSourceRange(),
+ E->getLocStart(),
+ /*IsStringLocation*/ false, SpecRange,
+ FixItHint::CreateReplacement(SpecRange, os.str()));
} else {
// The canonical type for formatting this value is different from the
@@ -3779,15 +4258,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// arguments here.
switch (S.isValidVarArgType(ExprTy)) {
case Sema::VAK_Valid:
- case Sema::VAK_ValidInCXX11:
+ case Sema::VAK_ValidInCXX11: {
+ unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
+ if (match == analyze_printf::ArgType::NoMatchPedantic) {
+ diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
+ }
+
EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
+ S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ << IsEnum << CSR << E->getSourceRange(),
+ E->getLocStart(), /*IsStringLocation*/ false, CSR);
break;
-
+ }
case Sema::VAK_Undefined:
case Sema::VAK_MSVCUndefined:
EmitFormatDiagnostic(
@@ -3919,13 +4401,13 @@ bool CheckScanfHandler::HandleScanfSpecifier(
FixItHint::CreateRemoval(R));
}
}
-
+
if (!FS.consumesDataArgument()) {
// FIXME: Technically specifying a precision or field width here
// makes no sense. Worth issuing a warning at some point.
return true;
}
-
+
// Consume the argument.
unsigned argIndex = FS.getArgIndex();
if (argIndex < NumDataArgs) {
@@ -3934,7 +4416,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
// function if we encounter some other error.
CoveredArgs.set(argIndex);
}
-
+
// Check the length modifier is valid with the given conversion specifier.
if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo()))
HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
@@ -3951,47 +4433,57 @@ bool CheckScanfHandler::HandleScanfSpecifier(
// The remaining checks depend on the data arguments.
if (HasVAListArg)
return true;
-
+
if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
return false;
-
+
// Check that the argument type matches the format specifier.
const Expr *Ex = getDataArg(argIndex);
if (!Ex)
return true;
const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);
- if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {
- ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(),
- Ex->IgnoreImpCasts()->getType(),
- S.getLangOpts(), S.Context);
-
- if (success) {
- // Get the fix string from the fixed format specifier.
- SmallString<128> buf;
- llvm::raw_svector_ostream os(buf);
- fixedFS.toString(os);
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false
- << Ex->getSourceRange(),
+ if (!AT.isValid()) {
+ return true;
+ }
+
+ analyze_format_string::ArgType::MatchKind match =
+ AT.matchesType(S.Context, Ex->getType());
+ if (match == analyze_format_string::ArgType::Match) {
+ return true;
+ }
+
+ ScanfSpecifier fixedFS = FS;
+ bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
+ S.getLangOpts(), S.Context);
+
+ unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
+ if (match == analyze_format_string::ArgType::NoMatchPedantic) {
+ diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
+ }
+
+ if (success) {
+ // Get the fix string from the fixed format specifier.
+ SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+ fixedFS.toString(os);
+
+ EmitFormatDiagnostic(
+ S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context)
+ << Ex->getType() << false << Ex->getSourceRange(),
Ex->getLocStart(),
- /*IsStringLocation*/false,
+ /*IsStringLocation*/ false,
getSpecifierRange(startSpecifier, specifierLen),
FixItHint::CreateReplacement(
- getSpecifierRange(startSpecifier, specifierLen),
- os.str()));
- } else {
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false
- << Ex->getSourceRange(),
- Ex->getLocStart(),
- /*IsStringLocation*/false,
- getSpecifierRange(startSpecifier, specifierLen));
- }
+ getSpecifierRange(startSpecifier, specifierLen), os.str()));
+ } else {
+ EmitFormatDiagnostic(S.PDiag(diag)
+ << AT.getRepresentativeTypeName(S.Context)
+ << Ex->getType() << false << Ex->getSourceRange(),
+ Ex->getLocStart(),
+ /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
}
return true;
@@ -4046,9 +4538,9 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
}
if (Type == FST_Printf || Type == FST_NSString ||
- Type == FST_FreeBSDKPrintf) {
+ Type == FST_FreeBSDKPrintf || Type == FST_OSTrace) {
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
- numDataArgs, (Type == FST_NSString),
+ numDataArgs, (Type == FST_NSString || Type == FST_OSTrace),
Str, HasVAListArg, Args, format_idx,
inFunctionCall, CallType, CheckedVarArgs);
@@ -4533,7 +5025,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T,
/// \brief If E is a sizeof expression, returns its argument expression,
/// otherwise returns NULL.
-static const Expr *getSizeOfExprArg(const Expr* E) {
+static const Expr *getSizeOfExprArg(const Expr *E) {
if (const UnaryExprOrTypeTraitExpr *SizeOf =
dyn_cast<UnaryExprOrTypeTraitExpr>(E))
if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
@@ -4543,7 +5035,7 @@ static const Expr *getSizeOfExprArg(const Expr* E) {
}
/// \brief If E is a sizeof expression, returns its argument type.
-static QualType getSizeOfArgType(const Expr* E) {
+static QualType getSizeOfArgType(const Expr *E) {
if (const UnaryExprOrTypeTraitExpr *SizeOf =
dyn_cast<UnaryExprOrTypeTraitExpr>(E))
if (SizeOf->getKind() == clang::UETT_SizeOf)
@@ -4589,8 +5081,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();
QualType DestTy = Dest->getType();
+ QualType PointeeTy;
if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
- QualType PointeeTy = DestPtrTy->getPointeeType();
+ PointeeTy = DestPtrTy->getPointeeType();
// Never warn about void type pointers. This can be used to suppress
// false positives.
@@ -4670,47 +5163,53 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
break;
}
}
+ } else if (DestTy->isArrayType()) {
+ PointeeTy = DestTy;
+ }
- // Always complain about dynamic classes.
- bool IsContained;
- if (const CXXRecordDecl *ContainedRD =
- getContainedDynamicClass(PointeeTy, IsContained)) {
-
- unsigned OperationType = 0;
- // "overwritten" if we're warning about the destination for any call
- // but memcmp; otherwise a verb appropriate to the call.
- if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
- if (BId == Builtin::BImemcpy)
- OperationType = 1;
- else if(BId == Builtin::BImemmove)
- OperationType = 2;
- else if (BId == Builtin::BImemcmp)
- OperationType = 3;
- }
-
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(diag::warn_dyn_class_memaccess)
- << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
- << FnName << IsContained << ContainedRD << OperationType
- << Call->getCallee()->getSourceRange());
- } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
- BId != Builtin::BImemset)
- DiagRuntimeBehavior(
- Dest->getExprLoc(), Dest,
- PDiag(diag::warn_arc_object_memaccess)
- << ArgIdx << FnName << PointeeTy
- << Call->getCallee()->getSourceRange());
- else
- continue;
+ if (PointeeTy == QualType())
+ continue;
+ // Always complain about dynamic classes.
+ bool IsContained;
+ if (const CXXRecordDecl *ContainedRD =
+ getContainedDynamicClass(PointeeTy, IsContained)) {
+
+ unsigned OperationType = 0;
+ // "overwritten" if we're warning about the destination for any call
+ // but memcmp; otherwise a verb appropriate to the call.
+ if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
+ if (BId == Builtin::BImemcpy)
+ OperationType = 1;
+ else if(BId == Builtin::BImemmove)
+ OperationType = 2;
+ else if (BId == Builtin::BImemcmp)
+ OperationType = 3;
+ }
+
DiagRuntimeBehavior(
Dest->getExprLoc(), Dest,
- PDiag(diag::note_bad_memaccess_silence)
- << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
- break;
- }
+ PDiag(diag::warn_dyn_class_memaccess)
+ << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
+ << FnName << IsContained << ContainedRD << OperationType
+ << Call->getCallee()->getSourceRange());
+ } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
+ BId != Builtin::BImemset)
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_arc_object_memaccess)
+ << ArgIdx << FnName << PointeeTy
+ << Call->getCallee()->getSourceRange());
+ else
+ continue;
+
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::note_bad_memaccess_silence)
+ << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ break;
}
+
}
// A little helper routine: ignore addition and subtraction of integer literals.
@@ -5316,7 +5815,8 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc);
// Check if the return value is null but should not be.
- if (Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs) &&
+ if (((Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs)) ||
+ (!isObjCMethod && isNonNullType(Context, lhsType))) &&
CheckNonNullExpr(*this, RetValExp))
Diag(ReturnLoc, diag::warn_null_ret)
<< (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange();
@@ -5861,7 +6361,7 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
// TODO: Investigate using GetExprRange() to get tighter bounds
// on the bit ranges.
QualType OtherT = Other->getType();
- if (const AtomicType *AT = dyn_cast<AtomicType>(OtherT))
+ if (const auto *AT = OtherT->getAs<AtomicType>())
OtherT = AT->getValueType();
IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
unsigned OtherWidth = OtherRange.Width;
@@ -6384,6 +6884,101 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
S.getFixItZeroLiteralForType(T, Loc));
}
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral);
+static void checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral);
+
+/// Check a single element within a collection literal against the
+/// target element type.
+static void checkObjCCollectionLiteralElement(Sema &S,
+ QualType TargetElementType,
+ Expr *Element,
+ unsigned ElementKind) {
+ // Skip a bitcast to 'id' or qualified 'id'.
+ if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {
+ if (ICE->getCastKind() == CK_BitCast &&
+ ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>())
+ Element = ICE->getSubExpr();
+ }
+
+ QualType ElementType = Element->getType();
+ ExprResult ElementResult(Element);
+ if (ElementType->getAs<ObjCObjectPointerType>() &&
+ S.CheckSingleAssignmentConstraints(TargetElementType,
+ ElementResult,
+ false, false)
+ != Sema::Compatible) {
+ S.Diag(Element->getLocStart(),
+ diag::warn_objc_collection_literal_element)
+ << ElementType << ElementKind << TargetElementType
+ << Element->getSourceRange();
+ }
+
+ if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))
+ checkObjCArrayLiteral(S, TargetElementType, ArrayLiteral);
+ else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element))
+ checkObjCDictionaryLiteral(S, TargetElementType, DictionaryLiteral);
+}
+
+/// Check an Objective-C array literal being converted to the given
+/// target type.
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral) {
+ if (!S.NSArrayDecl)
+ return;
+
+ const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
+ if (!TargetObjCPtr)
+ return;
+
+ if (TargetObjCPtr->isUnspecialized() ||
+ TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl()
+ != S.NSArrayDecl->getCanonicalDecl())
+ return;
+
+ auto TypeArgs = TargetObjCPtr->getTypeArgs();
+ if (TypeArgs.size() != 1)
+ return;
+
+ QualType TargetElementType = TypeArgs[0];
+ for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) {
+ checkObjCCollectionLiteralElement(S, TargetElementType,
+ ArrayLiteral->getElement(I),
+ 0);
+ }
+}
+
+/// Check an Objective-C dictionary literal being converted to the given
+/// target type.
+static void checkObjCDictionaryLiteral(
+ Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral) {
+ if (!S.NSDictionaryDecl)
+ return;
+
+ const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
+ if (!TargetObjCPtr)
+ return;
+
+ if (TargetObjCPtr->isUnspecialized() ||
+ TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl()
+ != S.NSDictionaryDecl->getCanonicalDecl())
+ return;
+
+ auto TypeArgs = TargetObjCPtr->getTypeArgs();
+ if (TypeArgs.size() != 2)
+ return;
+
+ QualType TargetKeyType = TypeArgs[0];
+ QualType TargetObjectType = TypeArgs[1];
+ for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) {
+ auto Element = DictionaryLiteral->getKeyValueElement(I);
+ checkObjCCollectionLiteralElement(S, TargetKeyType, Element.Key, 1);
+ checkObjCCollectionLiteralElement(S, TargetObjectType, Element.Value, 2);
+ }
+}
+
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
SourceLocation CC, bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -6423,6 +7018,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
+ // Check implicit casts from Objective-C collection literals to specialized
+ // collection types, e.g., NSArray<NSString *> *.
+ if (auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))
+ checkObjCArrayLiteral(S, QualType(Target, 0), ArrayLiteral);
+ else if (auto *DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(E))
+ checkObjCDictionaryLiteral(S, QualType(Target, 0), DictionaryLiteral);
+
// Strip vector types.
if (isa<VectorType>(Source)) {
if (!isa<VectorType>(Target)) {
@@ -6705,8 +7307,11 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
E = POE->getResultExpr();
}
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
- return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+ if (OVE->getSourceExpr())
+ AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
+ return;
+ }
// Skip past explicit casts.
if (isa<ExplicitCastExpr>(E)) {
@@ -6737,8 +7342,8 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
CC = E->getExprLoc();
BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
- for (Stmt::child_range I = E->children(); I; ++I) {
- Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
+ for (Stmt *SubStmt : E->children()) {
+ Expr *ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
if (!ChildExpr)
continue;
@@ -6788,7 +7393,7 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E,
if (!M->getMemberDecl()->getType()->isReferenceType())
return false;
} else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) {
- if (!Call->getCallReturnType()->isReferenceType())
+ if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType())
return false;
FD = Call->getDirectCallee();
} else {
@@ -7533,6 +8138,35 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
(void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
}
+static void diagnoseArrayStarInParamType(Sema &S, QualType PType,
+ SourceLocation Loc) {
+ if (!PType->isVariablyModifiedType())
+ return;
+ if (const auto *PointerTy = dyn_cast<PointerType>(PType)) {
+ diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc);
+ return;
+ }
+ if (const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) {
+ diagnoseArrayStarInParamType(S, ReferenceTy->getPointeeType(), Loc);
+ return;
+ }
+ if (const auto *ParenTy = dyn_cast<ParenType>(PType)) {
+ diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc);
+ return;
+ }
+
+ const ArrayType *AT = S.Context.getAsArrayType(PType);
+ if (!AT)
+ return;
+
+ if (AT->getSizeModifier() != ArrayType::Star) {
+ diagnoseArrayStarInParamType(S, AT->getElementType(), Loc);
+ return;
+ }
+
+ S.Diag(Loc, diag::err_array_star_in_function_definition);
+}
+
/// CheckParmsForFunctionDef - Check that the parameters of the given
/// function are appropriate for the definition of a function. This
/// takes care of any checks that cannot be performed on the
@@ -7571,15 +8205,9 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
// notation in their sequences of declarator specifiers to specify
// variable length array types.
QualType PType = Param->getOriginalType();
- while (const ArrayType *AT = Context.getAsArrayType(PType)) {
- if (AT->getSizeModifier() == ArrayType::Star) {
- // FIXME: This diagnostic should point the '[*]' if source-location
- // information is added for it.
- Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
- break;
- }
- PType= AT->getElementType();
- }
+ // FIXME: This diagnostic should point the '[*]' if source-location
+ // information is added for it.
+ diagnoseArrayStarInParamType(*this, PType, Param->getLocation());
// MSVC destroys objects passed by value in the callee. Therefore a
// function definition which takes such a parameter must be able to call the
@@ -8097,6 +8725,236 @@ static bool isSetterLikeSelector(Selector sel) {
return !isLowercase(str.front());
}
+static Optional<int> GetNSMutableArrayArgumentIndex(Sema &S,
+ ObjCMessageExpr *Message) {
+ if (S.NSMutableArrayPointer.isNull()) {
+ IdentifierInfo *NSMutableArrayId =
+ S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableArray);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableArrayId,
+ Message->getLocStart(),
+ Sema::LookupOrdinaryName);
+ ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!InterfaceDecl) {
+ return None;
+ }
+ QualType NSMutableArrayObject =
+ S.Context.getObjCInterfaceType(InterfaceDecl);
+ S.NSMutableArrayPointer =
+ S.Context.getObjCObjectPointerType(NSMutableArrayObject);
+ }
+
+ if (S.NSMutableArrayPointer != Message->getReceiverType()) {
+ return None;
+ }
+
+ Selector Sel = Message->getSelector();
+
+ Optional<NSAPI::NSArrayMethodKind> MKOpt =
+ S.NSAPIObj->getNSArrayMethodKind(Sel);
+ if (!MKOpt) {
+ return None;
+ }
+
+ NSAPI::NSArrayMethodKind MK = *MKOpt;
+
+ switch (MK) {
+ case NSAPI::NSMutableArr_addObject:
+ case NSAPI::NSMutableArr_insertObjectAtIndex:
+ case NSAPI::NSMutableArr_setObjectAtIndexedSubscript:
+ return 0;
+ case NSAPI::NSMutableArr_replaceObjectAtIndex:
+ return 1;
+
+ default:
+ return None;
+ }
+
+ return None;
+}
+
+static
+Optional<int> GetNSMutableDictionaryArgumentIndex(Sema &S,
+ ObjCMessageExpr *Message) {
+
+ if (S.NSMutableDictionaryPointer.isNull()) {
+ IdentifierInfo *NSMutableDictionaryId =
+ S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableDictionary);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableDictionaryId,
+ Message->getLocStart(),
+ Sema::LookupOrdinaryName);
+ ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!InterfaceDecl) {
+ return None;
+ }
+ QualType NSMutableDictionaryObject =
+ S.Context.getObjCInterfaceType(InterfaceDecl);
+ S.NSMutableDictionaryPointer =
+ S.Context.getObjCObjectPointerType(NSMutableDictionaryObject);
+ }
+
+ if (S.NSMutableDictionaryPointer != Message->getReceiverType()) {
+ return None;
+ }
+
+ Selector Sel = Message->getSelector();
+
+ Optional<NSAPI::NSDictionaryMethodKind> MKOpt =
+ S.NSAPIObj->getNSDictionaryMethodKind(Sel);
+ if (!MKOpt) {
+ return None;
+ }
+
+ NSAPI::NSDictionaryMethodKind MK = *MKOpt;
+
+ switch (MK) {
+ case NSAPI::NSMutableDict_setObjectForKey:
+ case NSAPI::NSMutableDict_setValueForKey:
+ case NSAPI::NSMutableDict_setObjectForKeyedSubscript:
+ return 0;
+
+ default:
+ return None;
+ }
+
+ return None;
+}
+
+static Optional<int> GetNSSetArgumentIndex(Sema &S, ObjCMessageExpr *Message) {
+
+ ObjCInterfaceDecl *InterfaceDecl;
+ if (S.NSMutableSetPointer.isNull()) {
+ IdentifierInfo *NSMutableSetId =
+ S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableSet);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableSetId,
+ Message->getLocStart(),
+ Sema::LookupOrdinaryName);
+ InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (InterfaceDecl) {
+ QualType NSMutableSetObject =
+ S.Context.getObjCInterfaceType(InterfaceDecl);
+ S.NSMutableSetPointer =
+ S.Context.getObjCObjectPointerType(NSMutableSetObject);
+ }
+ }
+
+ if (S.NSCountedSetPointer.isNull()) {
+ IdentifierInfo *NSCountedSetId =
+ S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSCountedSet);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, NSCountedSetId,
+ Message->getLocStart(),
+ Sema::LookupOrdinaryName);
+ InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (InterfaceDecl) {
+ QualType NSCountedSetObject =
+ S.Context.getObjCInterfaceType(InterfaceDecl);
+ S.NSCountedSetPointer =
+ S.Context.getObjCObjectPointerType(NSCountedSetObject);
+ }
+ }
+
+ if (S.NSMutableOrderedSetPointer.isNull()) {
+ IdentifierInfo *NSOrderedSetId =
+ S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableOrderedSet);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, NSOrderedSetId,
+ Message->getLocStart(),
+ Sema::LookupOrdinaryName);
+ InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (InterfaceDecl) {
+ QualType NSOrderedSetObject =
+ S.Context.getObjCInterfaceType(InterfaceDecl);
+ S.NSMutableOrderedSetPointer =
+ S.Context.getObjCObjectPointerType(NSOrderedSetObject);
+ }
+ }
+
+ QualType ReceiverType = Message->getReceiverType();
+
+ bool IsMutableSet = !S.NSMutableSetPointer.isNull() &&
+ ReceiverType == S.NSMutableSetPointer;
+ bool IsMutableOrderedSet = !S.NSMutableOrderedSetPointer.isNull() &&
+ ReceiverType == S.NSMutableOrderedSetPointer;
+ bool IsCountedSet = !S.NSCountedSetPointer.isNull() &&
+ ReceiverType == S.NSCountedSetPointer;
+
+ if (!IsMutableSet && !IsMutableOrderedSet && !IsCountedSet) {
+ return None;
+ }
+
+ Selector Sel = Message->getSelector();
+
+ Optional<NSAPI::NSSetMethodKind> MKOpt = S.NSAPIObj->getNSSetMethodKind(Sel);
+ if (!MKOpt) {
+ return None;
+ }
+
+ NSAPI::NSSetMethodKind MK = *MKOpt;
+
+ switch (MK) {
+ case NSAPI::NSMutableSet_addObject:
+ case NSAPI::NSOrderedSet_setObjectAtIndex:
+ case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript:
+ case NSAPI::NSOrderedSet_insertObjectAtIndex:
+ return 0;
+ case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject:
+ return 1;
+ }
+
+ return None;
+}
+
+void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
+ if (!Message->isInstanceMessage()) {
+ return;
+ }
+
+ Optional<int> ArgOpt;
+
+ if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) &&
+ !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) &&
+ !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) {
+ return;
+ }
+
+ int ArgIndex = *ArgOpt;
+
+ Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();
+ if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {
+ Receiver = OE->getSourceExpr()->IgnoreImpCasts();
+ }
+
+ Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts();
+ if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) {
+ Arg = OE->getSourceExpr()->IgnoreImpCasts();
+ }
+
+ if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {
+ if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
+ if (ReceiverRE->getDecl() == ArgRE->getDecl()) {
+ ValueDecl *Decl = ReceiverRE->getDecl();
+ Diag(Message->getSourceRange().getBegin(),
+ diag::warn_objc_circular_container)
+ << Decl->getName();
+ Diag(Decl->getLocation(),
+ diag::note_objc_circular_container_declared_here)
+ << Decl->getName();
+ }
+ }
+ } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {
+ if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {
+ if (IvarRE->getDecl() == IvarArgRE->getDecl()) {
+ ObjCIvarDecl *Decl = IvarRE->getDecl();
+ Diag(Message->getSourceRange().getBegin(),
+ diag::warn_objc_circular_container)
+ << Decl->getName();
+ Diag(Decl->getLocation(),
+ diag::note_objc_circular_container_declared_here)
+ << Decl->getName();
+ }
+ }
+ }
+
+}
+
/// Check a message send to see if it's likely to cause a retain cycle.
void Sema::checkRetainCycles(ObjCMessageExpr *msg) {
// Only check instance methods whose selector looks like a setter.
@@ -8281,7 +9139,7 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
// Get line numbers of statement and body.
bool StmtLineInvalid;
- unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc,
+ unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc,
&StmtLineInvalid);
if (StmtLineInvalid)
return false;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 48bdd2a..8626527 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -495,7 +495,6 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
AsNestedNameSpecifier = false;
ND = ND->getUnderlyingDecl();
- unsigned IDNS = ND->getIdentifierNamespace();
// Skip unnamed entities.
if (!ND->getDeclName())
@@ -503,7 +502,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
// Friend declarations and declarations introduced due to friends are never
// added as results.
- if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
+ if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
return false;
// Class template (partial) specializations are never added as results.
@@ -800,8 +799,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(RecordTy));
- DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
- for (DeclContext::lookup_const_iterator I = Ctors.begin(),
+ DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
+ for (DeclContext::lookup_iterator I = Ctors.begin(),
E = Ctors.end();
I != E; ++I) {
R.Declaration = *I;
@@ -1019,9 +1018,7 @@ void ResultBuilder::AddResult(Result R) {
}
/// \brief Enter into a new scope.
-void ResultBuilder::EnterNewScope() {
- ShadowMaps.push_back(ShadowMap());
-}
+void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
/// \brief Exit from the current scope.
void ResultBuilder::ExitScope() {
@@ -1344,6 +1341,11 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
+
+ // Nullability
+ Results.AddResult(Result("_Nonnull", CCP_Type));
+ Results.AddResult(Result("_Null_unspecified", CCP_Type));
+ Results.AddResult(Result("_Nullable", CCP_Type));
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
@@ -2018,7 +2020,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
if (SemaRef.getLangOpts().C11) {
// _Alignof
Builder.AddResultTypeChunk("size_t");
- if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
+ if (SemaRef.PP.isMacroDefined("alignof"))
Builder.AddTypedTextChunk("alignof");
else
Builder.AddTypedTextChunk("_Alignof");
@@ -2055,6 +2057,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
const NamedDecl *ND,
+ QualType BaseType,
CodeCompletionBuilder &Result) {
if (!ND)
return;
@@ -2068,16 +2071,28 @@ static void AddResultTypeChunk(ASTContext &Context,
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getReturnType();
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
- T = Method->getReturnType();
- else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Method->getSendResultType(BaseType);
+ else
+ T = Method->getReturnType();
+ } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
+ } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Ivar->getUsageType(BaseType);
+ else
+ T = Ivar->getType();
} else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
T = Value->getType();
- } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
- T = Property->getType();
+ } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
+ if (!BaseType.isNull())
+ T = Property->getUsageType(BaseType);
+ else
+ T = Property->getType();
+ }
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
@@ -2086,22 +2101,22 @@ static void AddResultTypeChunk(ASTContext &Context,
Result.getAllocator()));
}
-static void MaybeAddSentinel(ASTContext &Context,
+static void MaybeAddSentinel(Preprocessor &PP,
const NamedDecl *FunctionOrMethod,
CodeCompletionBuilder &Result) {
if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
if (Sentinel->getSentinel() == 0) {
- if (Context.getLangOpts().ObjC1 &&
- Context.Idents.get("nil").hasMacroDefinition())
+ if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Result.AddTextChunk(", nil");
- else if (Context.Idents.get("NULL").hasMacroDefinition())
+ else if (PP.isMacroDefined("NULL"))
Result.AddTextChunk(", NULL");
else
Result.AddTextChunk(", (void*)0");
}
}
-static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
+static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
+ QualType &Type) {
std::string Result;
if (ObjCQuals & Decl::OBJC_TQ_In)
Result += "in ";
@@ -2115,14 +2130,31 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
Result += "byref ";
if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Result += "oneway ";
+ if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
+ if (auto nullability = AttributedType::stripOuterNullability(Type)) {
+ switch (*nullability) {
+ case NullabilityKind::NonNull:
+ Result += "nonnull ";
+ break;
+
+ case NullabilityKind::Nullable:
+ Result += "nullable ";
+ break;
+
+ case NullabilityKind::Unspecified:
+ Result += "null_unspecified ";
+ break;
+ }
+ }
+ }
return Result;
}
-static std::string FormatFunctionParameter(ASTContext &Context,
- const PrintingPolicy &Policy,
+static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
const ParmVarDecl *Param,
bool SuppressName = false,
- bool SuppressBlock = false) {
+ bool SuppressBlock = false,
+ Optional<ArrayRef<QualType>> ObjCSubsts = None) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
@@ -2133,13 +2165,18 @@ static std::string FormatFunctionParameter(ASTContext &Context,
if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Result = Param->getIdentifier()->getName();
- Param->getType().getAsStringInternal(Result, Policy);
-
+ QualType Type = Param->getType();
+ if (ObjCSubsts)
+ Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
+ ObjCSubstitutionContext::Parameter);
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
- + Result + ")";
+ Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
+ Type);
+ Result += Type.getAsString(Policy) + ")";
if (Param->getIdentifier() && !SuppressName)
Result += Param->getIdentifier()->getName();
+ } else {
+ Type.getAsStringInternal(Result, Policy);
}
return Result;
}
@@ -2167,6 +2204,11 @@ static std::string FormatFunctionParameter(ASTContext &Context,
TL = QualifiedTL.getUnqualifiedLoc();
continue;
}
+
+ if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
+ TL = AttrTL.getModifiedLoc();
+ continue;
+ }
}
// Try to get the function prototype behind the block pointer type,
@@ -2187,13 +2229,16 @@ static std::string FormatFunctionParameter(ASTContext &Context,
if (!ObjCMethodParam && Param->getIdentifier())
Result = Param->getIdentifier()->getName();
- Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
+ QualType Type = Param->getType().getUnqualifiedType();
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
- + Result + ")";
+ Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
+ Type);
+ Result += Type.getAsString(Policy) + Result + ")";
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
+ } else {
+ Type.getAsStringInternal(Result, Policy);
}
return Result;
@@ -2203,6 +2248,10 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// written in the source.
std::string Result;
QualType ResultType = Block.getTypePtr()->getReturnType();
+ if (ObjCSubsts)
+ ResultType = ResultType.substObjCTypeArgs(Param->getASTContext(),
+ *ObjCSubsts,
+ ObjCSubstitutionContext::Result);
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
@@ -2218,9 +2267,10 @@ static std::string FormatFunctionParameter(ASTContext &Context,
for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
if (I)
Params += ", ";
- Params += FormatFunctionParameter(Context, Policy, Block.getParam(I),
+ Params += FormatFunctionParameter(Policy, Block.getParam(I),
/*SuppressName=*/false,
- /*SuppressBlock=*/true);
+ /*SuppressBlock=*/true,
+ ObjCSubsts);
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
@@ -2248,7 +2298,7 @@ static std::string FormatFunctionParameter(ASTContext &Context,
}
/// \brief Add function parameter chunks to the given code completion string.
-static void AddFunctionParameterChunks(ASTContext &Context,
+static void AddFunctionParameterChunks(Preprocessor &PP,
const PrintingPolicy &Policy,
const FunctionDecl *Function,
CodeCompletionBuilder &Result,
@@ -2266,7 +2316,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
Result.getCodeCompletionTUInfo());
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
- AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
+ AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Result.AddOptionalChunk(Opt.TakeString());
break;
}
@@ -2279,9 +2329,8 @@ static void AddFunctionParameterChunks(ASTContext &Context,
InOptional = false;
// Format the placeholder string.
- std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
- Param);
-
+ std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
+
if (Function->isVariadic() && P == N - 1)
PlaceholderStr += ", ...";
@@ -2296,7 +2345,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
if (Proto->getNumParams() == 0)
Result.AddPlaceholderChunk("...");
- MaybeAddSentinel(Context, Function, Result);
+ MaybeAddSentinel(PP, Function, Result);
}
}
@@ -2309,7 +2358,11 @@ static void AddTemplateParameterChunks(ASTContext &Context,
unsigned Start = 0,
bool InDefaultArg = false) {
bool FirstParameter = true;
-
+
+ // Prefer to take the template parameter names from the first declaration of
+ // the template.
+ Template = cast<TemplateDecl>(Template->getCanonicalDecl());
+
TemplateParameterList *Params = Template->getTemplateParameters();
TemplateParameterList::iterator PEnd = Params->end();
if (MaxParameters)
@@ -2511,11 +2564,12 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
}
CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
- return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
- IncludeBriefComments);
+ return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
+ CCTUInfo, IncludeBriefComments);
}
/// \brief If possible, create a new code completion string for the given
@@ -2527,6 +2581,7 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
CodeCompletionString *
CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Preprocessor &PP,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
@@ -2572,11 +2627,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
}
if (Kind == RK_Macro) {
- const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro);
- assert(MD && "Not a macro?");
- const MacroInfo *MI = MD->getMacroInfo();
- assert((!MD->isDefined() || MI) && "missing MacroInfo for define");
-
+ const MacroInfo *MI = PP.getMacroInfo(Macro);
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Macro->getName()));
@@ -2644,14 +2695,14 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
for (const auto *I : ND->specific_attrs<AnnotateAttr>())
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
- AddResultTypeChunk(Ctx, Policy, ND, Result);
+ AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- AddFunctionParameterChunks(Ctx, Policy, Function, Result);
+ AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
@@ -2705,7 +2756,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
// Add the function parameters
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- AddFunctionParameterChunks(Ctx, Policy, Function, Result);
+ AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
@@ -2764,13 +2815,22 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
continue;
std::string Arg;
-
- if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
- Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
+ QualType ParamType = (*P)->getType();
+ Optional<ArrayRef<QualType>> ObjCSubsts;
+ if (!CCContext.getBaseType().isNull())
+ ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
+
+ if (ParamType->isBlockPointerType() && !DeclaringEntity)
+ Arg = FormatFunctionParameter(Policy, *P, true,
+ /*SuppressBlock=*/false,
+ ObjCSubsts);
else {
- (*P)->getType().getAsStringInternal(Arg, Policy);
- Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
- + Arg + ")";
+ if (ObjCSubsts)
+ ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
+ ObjCSubstitutionContext::Parameter);
+ Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
+ ParamType);
+ Arg += ParamType.getAsString(Policy) + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
@@ -2797,7 +2857,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddPlaceholderChunk(", ...");
}
- MaybeAddSentinel(Ctx, Method, Result);
+ MaybeAddSentinel(PP, Method, Result);
}
return Result.TakeString();
@@ -2812,73 +2872,115 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
+/// \brief Add function overload parameter chunks to the given code completion
+/// string.
+static void AddOverloadParameterChunks(ASTContext &Context,
+ const PrintingPolicy &Policy,
+ const FunctionDecl *Function,
+ const FunctionProtoType *Prototype,
+ CodeCompletionBuilder &Result,
+ unsigned CurrentArg,
+ unsigned Start = 0,
+ bool InOptional = false) {
+ bool FirstParameter = true;
+ unsigned NumParams = Function ? Function->getNumParams()
+ : Prototype->getNumParams();
+
+ for (unsigned P = Start; P != NumParams; ++P) {
+ if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
+ // When we see an optional default argument, put that argument and
+ // the remaining default arguments into a new, optional string.
+ CodeCompletionBuilder Opt(Result.getAllocator(),
+ Result.getCodeCompletionTUInfo());
+ if (!FirstParameter)
+ Opt.AddChunk(CodeCompletionString::CK_Comma);
+ // Optional sections are nested.
+ AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
+ CurrentArg, P, /*InOptional=*/true);
+ Result.AddOptionalChunk(Opt.TakeString());
+ return;
+ }
+
+ if (FirstParameter)
+ FirstParameter = false;
+ else
+ Result.AddChunk(CodeCompletionString::CK_Comma);
+
+ InOptional = false;
+
+ // Format the placeholder string.
+ std::string Placeholder;
+ if (Function)
+ Placeholder = FormatFunctionParameter(Policy, Function->getParamDecl(P));
+ else
+ Placeholder = Prototype->getParamType(P).getAsString(Policy);
+
+ if (P == CurrentArg)
+ Result.AddCurrentParameterChunk(
+ Result.getAllocator().CopyString(Placeholder));
+ else
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
+ }
+
+ if (Prototype && Prototype->isVariadic()) {
+ CodeCompletionBuilder Opt(Result.getAllocator(),
+ Result.getCodeCompletionTUInfo());
+ if (!FirstParameter)
+ Opt.AddChunk(CodeCompletionString::CK_Comma);
+
+ if (CurrentArg < NumParams)
+ Opt.AddPlaceholderChunk("...");
+ else
+ Opt.AddCurrentParameterChunk("...");
+
+ Result.AddOptionalChunk(Opt.TakeString());
+ }
+}
+
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
- unsigned CurrentArg,
- Sema &S,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo) const {
+ unsigned CurrentArg, Sema &S,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments) const {
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
// FIXME: Set priority, availability appropriately.
CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
FunctionDecl *FDecl = getFunction();
- AddResultTypeChunk(S.Context, Policy, FDecl, Result);
- const FunctionProtoType *Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
- Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context,
- Policy, Result.getAllocator()));
+ Result.AddResultTypeChunk(Result.getAllocator().CopyString(
+ FT->getReturnType().getAsString(Policy)));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
-
- if (FDecl)
+
+ if (FDecl) {
+ if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
+ if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
+ FDecl->getParamDecl(CurrentArg)))
+ Result.addBriefComment(RC->getBriefText(S.getASTContext()));
+ AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
- Result.getAllocator().CopyString(FDecl->getNameAsString()));
- else
- Result.AddTextChunk(Result.getAllocator().CopyString(
+ Result.getAllocator().CopyString(FDecl->getNameAsString()));
+ } else {
+ Result.AddResultTypeChunk(
+ Result.getAllocator().CopyString(
Proto->getReturnType().getAsString(Policy)));
+ }
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams();
- for (unsigned I = 0; I != NumParams; ++I) {
- if (I)
- Result.AddChunk(CodeCompletionString::CK_Comma);
-
- std::string ArgString;
- QualType ArgType;
-
- if (FDecl) {
- ArgString = FDecl->getParamDecl(I)->getNameAsString();
- ArgType = FDecl->getParamDecl(I)->getOriginalType();
- } else {
- ArgType = Proto->getParamType(I);
- }
-
- ArgType.getAsStringInternal(ArgString, Policy);
-
- if (I == CurrentArg)
- Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
- Result.getAllocator().CopyString(ArgString));
- else
- Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
- }
-
- if (Proto && Proto->isVariadic()) {
- Result.AddChunk(CodeCompletionString::CK_Comma);
- if (CurrentArg < NumParams)
- Result.AddTextChunk("...");
- else
- Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
- }
+ AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
+ CurrentArg);
Result.AddChunk(CodeCompletionString::CK_RightParen);
-
+
return Result.TakeString();
}
@@ -2964,7 +3066,9 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::Import:
return CXCursor_ModuleImportDecl;
-
+
+ case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
+
default:
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {
@@ -2990,8 +3094,9 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
- if (IncludeUndefined || M->first->hasMacroDefinition()) {
- if (MacroInfo *MI = M->second->getMacroInfo())
+ auto MD = PP.getMacroDefinition(M->first);
+ if (IncludeUndefined || MD) {
+ if (MacroInfo *MI = MD.getMacroInfo())
if (MI->isUsedForHeaderGuard())
continue;
@@ -3454,7 +3559,8 @@ static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
return Container;
}
-static void AddObjCProperties(ObjCContainerDecl *Container,
+static void AddObjCProperties(const CodeCompletionContext &CCContext,
+ ObjCContainerDecl *Container,
bool AllowCategories,
bool AllowNullaryMethods,
DeclContext *CurContext,
@@ -3481,7 +3587,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
if (AddedProperties.insert(Name).second) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- AddResultTypeChunk(Context, Policy, M, Builder);
+ AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(),
+ Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
@@ -3496,32 +3603,32 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
- AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
for (auto *Cat : IFace->known_categories())
- AddObjCProperties(Cat, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
}
// Look through protocols.
for (auto *I : IFace->all_referenced_protocols())
- AddObjCProperties(I, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
// Look in the superclass.
if (IFace->getSuperClass())
- AddObjCProperties(IFace->getSuperClass(), AllowCategories,
+ AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
AllowNullaryMethods, CurContext,
AddedProperties, Results);
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (auto *P : Category->protocols())
- AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
+ CurContext, AddedProperties, Results);
}
}
@@ -3563,11 +3670,11 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
contextKind = CodeCompletionContext::CCC_DotMemberAccess;
}
}
-
+
+ CodeCompletionContext CCContext(contextKind, BaseType);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext(contextKind,
- BaseType),
+ CCContext,
&ResultBuilder::IsMember);
Results.EnterNewScope();
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
@@ -3607,14 +3714,14 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
const ObjCObjectPointerType *ObjCPtr
= BaseType->getAsObjCInterfacePointerType();
assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
+ AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
/*AllowNullaryMethods=*/true, CurContext,
AddedProperties, Results);
// Add properties from the protocols in a qualified interface.
for (auto *I : ObjCPtr->quals())
- AddObjCProperties(I, true, /*AllowNullaryMethods=*/true, CurContext,
- AddedProperties, Results);
+ AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
+ CurContext, AddedProperties, Results);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
@@ -3816,7 +3923,74 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) {
return false;
}
-void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
+typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+
+static void mergeCandidatesWithResults(Sema &SemaRef,
+ SmallVectorImpl<ResultCandidate> &Results,
+ OverloadCandidateSet &CandidateSet,
+ SourceLocation Loc) {
+ if (!CandidateSet.empty()) {
+ // Sort the overload candidate set by placing the best overloads first.
+ std::stable_sort(
+ CandidateSet.begin(), CandidateSet.end(),
+ [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
+ return isBetterOverloadCandidate(SemaRef, X, Y, Loc);
+ });
+
+ // Add the remaining viable overload candidates as code-completion results.
+ for (auto &Candidate : CandidateSet)
+ if (Candidate.Viable)
+ Results.push_back(ResultCandidate(Candidate.Function));
+ }
+}
+
+/// \brief Get the type of the Nth parameter from a given set of overload
+/// candidates.
+static QualType getParamType(Sema &SemaRef,
+ ArrayRef<ResultCandidate> Candidates,
+ unsigned N) {
+
+ // Given the overloads 'Candidates' for a function call matching all arguments
+ // up to N, return the type of the Nth parameter if it is the same for all
+ // overload candidates.
+ QualType ParamType;
+ for (auto &Candidate : Candidates) {
+ if (auto FType = Candidate.getFunctionType())
+ if (auto Proto = dyn_cast<FunctionProtoType>(FType))
+ if (N < Proto->getNumParams()) {
+ if (ParamType.isNull())
+ ParamType = Proto->getParamType(N);
+ else if (!SemaRef.Context.hasSameUnqualifiedType(
+ ParamType.getNonReferenceType(),
+ Proto->getParamType(N).getNonReferenceType()))
+ // Otherwise return a default-constructed QualType.
+ return QualType();
+ }
+ }
+
+ return ParamType;
+}
+
+static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
+ MutableArrayRef<ResultCandidate> Candidates,
+ unsigned CurrentArg,
+ bool CompleteExpressionWithCurrentArg = true) {
+ QualType ParamType;
+ if (CompleteExpressionWithCurrentArg)
+ ParamType = getParamType(SemaRef, Candidates, CurrentArg);
+
+ if (ParamType.isNull())
+ SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
+ else
+ SemaRef.CodeCompleteExpression(S, ParamType);
+
+ if (!Candidates.empty())
+ SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
+ Candidates.data(),
+ Candidates.size());
+}
+
+void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
if (!CodeCompleter)
return;
@@ -3825,7 +3999,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
// results. We may want to revisit this strategy in the future,
// e.g., by merging the two kinds of results.
- Expr *Fn = (Expr *)FnIn;
+ // FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
@@ -3838,92 +4012,120 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
SourceLocation Loc = Fn->getExprLoc();
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- // FIXME: What if we're calling something that isn't a function declaration?
- // FIXME: What if we're calling a pseudo-destructor?
- // FIXME: What if we're calling a member function?
-
- typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
SmallVector<ResultCandidate, 8> Results;
Expr *NakedFn = Fn->IgnoreParenCasts();
- if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+ if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
AddOverloadedCallCandidates(ULE, Args, CandidateSet,
- /*PartialOverloading=*/ true);
- else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
- FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
- if (FDecl) {
- if (!getLangOpts().CPlusPlus ||
- !FDecl->getType()->getAs<FunctionProtoType>())
- Results.push_back(ResultCandidate(FDecl));
+ /*PartialOverloading=*/true);
+ else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
+ if (UME->hasExplicitTemplateArgs()) {
+ UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
+ TemplateArgs = &TemplateArgsBuffer;
+ }
+ SmallVector<Expr *, 12> ArgExprs(1, UME->getBase());
+ ArgExprs.append(Args.begin(), Args.end());
+ UnresolvedSet<8> Decls;
+ Decls.append(UME->decls_begin(), UME->decls_end());
+ AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
+ } else {
+ FunctionDecl *FD = nullptr;
+ if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
+ FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
+ else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
+ FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FD) { // We check whether it's a resolved function declaration.
+ if (!getLangOpts().CPlusPlus ||
+ !FD->getType()->getAs<FunctionProtoType>())
+ Results.push_back(ResultCandidate(FD));
else
- // FIXME: access?
- AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
- CandidateSet, false, /*PartialOverloading*/true);
+ AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
+ Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
+
+ } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
+ // If expression's type is CXXRecordDecl, it may overload the function
+ // call operator, so we check if it does and add them as candidates.
+ // A complete type is needed to lookup for member function call operators.
+ if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) {
+ DeclarationName OpName = Context.DeclarationNames
+ .getCXXOperatorName(OO_Call);
+ LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
+ LookupQualifiedName(R, DC);
+ R.suppressDiagnostics();
+ SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
+ ArgExprs.append(Args.begin(), Args.end());
+ AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
+ /*ExplicitArgs=*/nullptr,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
+ }
+ } else {
+ // Lastly we check whether expression's type is function pointer or
+ // function.
+ QualType T = NakedFn->getType();
+ if (!T->getPointeeType().isNull())
+ T = T->getPointeeType();
+
+ if (auto FP = T->getAs<FunctionProtoType>()) {
+ if (!TooManyArguments(FP->getNumParams(), Args.size(),
+ /*PartialOverloading=*/true) ||
+ FP->isVariadic())
+ Results.push_back(ResultCandidate(FP));
+ } else if (auto FT = T->getAs<FunctionType>())
+ // No prototype and declaration, it may be a K & R style function.
+ Results.push_back(ResultCandidate(FT));
}
}
-
- QualType ParamType;
-
- if (!CandidateSet.empty()) {
- // Sort the overload candidate set by placing the best overloads first.
- std::stable_sort(
- CandidateSet.begin(), CandidateSet.end(),
- [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
- return isBetterOverloadCandidate(*this, X, Y, Loc);
- });
- // Add the remaining viable overload candidates as code-completion reslults.
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
- CandEnd = CandidateSet.end();
- Cand != CandEnd; ++Cand) {
- if (Cand->Viable)
- Results.push_back(ResultCandidate(Cand->Function));
- }
-
- // From the viable candidates, try to determine the type of this parameter.
- for (unsigned I = 0, N = Results.size(); I != N; ++I) {
- if (const FunctionType *FType = Results[I].getFunctionType())
- if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
- if (Args.size() < Proto->getNumParams()) {
- if (ParamType.isNull())
- ParamType = Proto->getParamType(Args.size());
- else if (!Context.hasSameUnqualifiedType(
- ParamType.getNonReferenceType(),
- Proto->getParamType(Args.size())
- .getNonReferenceType())) {
- ParamType = QualType();
- break;
- }
- }
- }
- } else {
- // Try to determine the parameter type from the type of the expression
- // being called.
- QualType FunctionType = Fn->getType();
- if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
- FunctionType = Ptr->getPointeeType();
- else if (const BlockPointerType *BlockPtr
- = FunctionType->getAs<BlockPointerType>())
- FunctionType = BlockPtr->getPointeeType();
- else if (const MemberPointerType *MemPtr
- = FunctionType->getAs<MemberPointerType>())
- FunctionType = MemPtr->getPointeeType();
-
- if (const FunctionProtoType *Proto
- = FunctionType->getAs<FunctionProtoType>()) {
- if (Args.size() < Proto->getNumParams())
- ParamType = Proto->getParamType(Args.size());
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ CodeCompleteOverloadResults(*this, S, Results, Args.size(),
+ !CandidateSet.empty());
+}
+
+void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
+ ArrayRef<Expr *> Args) {
+ if (!CodeCompleter)
+ return;
+
+ // A complete type is needed to lookup for constructors.
+ if (RequireCompleteType(Loc, Type, 0))
+ return;
+
+ CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
+ if (!RD) {
+ CodeCompleteExpression(S, Type);
+ return;
+ }
+
+ // FIXME: Provide support for member initializers.
+ // FIXME: Provide support for variadic template constructors.
+
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
+
+ for (auto C : LookupConstructors(RD)) {
+ if (auto FD = dyn_cast<FunctionDecl>(C)) {
+ AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
+ Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
+ } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
+ AddTemplateOverloadCandidate(FTD,
+ DeclAccessPair::make(FTD, C->getAccess()),
+ /*ExplicitTemplateArgs=*/nullptr,
+ Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
}
}
- if (ParamType.isNull())
- CodeCompleteOrdinaryName(S, PCC_Expression);
- else
- CodeCompleteExpression(S, ParamType);
-
- if (!Results.empty())
- CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
- Results.size());
+ SmallVector<ResultCandidate, 8> Results;
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ CodeCompleteOverloadResults(*this, S, Results, Args.size());
}
void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
@@ -4207,9 +4409,12 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
void Sema::CodeCompleteConstructorInitializer(
Decl *ConstructorD,
ArrayRef <CXXCtorInitializer *> Initializers) {
- PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
- CXXConstructorDecl *Constructor
- = static_cast<CXXConstructorDecl *>(ConstructorD);
+ if (!ConstructorD)
+ return;
+
+ AdjustDeclIfTemplate(ConstructorD);
+
+ CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
@@ -4233,6 +4438,7 @@ void Sema::CodeCompleteConstructorInitializer(
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
+ PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
for (const auto &Base : ClassDecl->bases()) {
@@ -4726,6 +4932,12 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Getter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Getter.TakeString()));
}
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
+ Results.AddResult(CodeCompletionResult("nonnull"));
+ Results.AddResult(CodeCompletionResult("nullable"));
+ Results.AddResult(CodeCompletionResult("null_unspecified"));
+ Results.AddResult(CodeCompletionResult("null_resettable"));
+ }
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
@@ -4975,13 +5187,18 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
Results.AddResult("byref");
Results.AddResult("oneway");
}
+ if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
+ Results.AddResult("nonnull");
+ Results.AddResult("nullable");
+ Results.AddResult("null_unspecified");
+ }
// If we're completing the return type of an Objective-C method and the
// identifier IBAction refers to a macro, provide a completion item for
// an action, e.g.,
// IBAction)<#selector#>:(id)sender
if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
- Context.Idents.get("IBAction").hasMacroDefinition()) {
+ PP.isMacroDefined("IBAction")) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo(),
CCP_CodePattern, CXAvailability_Available);
@@ -5162,7 +5379,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Results.getCodeCompletionTUInfo());
// Give this completion a return type.
- AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
+ AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
+ Results.getCompletionContext().getBaseType(),
Builder);
// If we need the "super" keyword, add it (plus some spacing).
@@ -5916,9 +6134,10 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
}
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
+ CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CCContext);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
@@ -5939,11 +6158,12 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Results.EnterNewScope();
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
- AddObjCProperties(ClassImpl->getClassInterface(), false,
+ AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
/*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
else
- AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+ AddObjCProperties(CCContext,
+ cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
false, /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
Results.ExitScope();
@@ -6147,7 +6367,7 @@ static void AddObjCPassingTypeChunk(QualType Type,
const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
+ std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
if (!Quals.empty())
Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
@@ -6860,7 +7080,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getReturnType(),
+ AddObjCPassingTypeChunk(Method->getSendResultType()
+ .stripObjCKindOfType(Context),
Method->getObjCDeclQualifier(), Context, Policy,
Builder);
@@ -6886,7 +7107,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
break;
// Add the parameter type.
- AddObjCPassingTypeChunk((*P)->getOriginalType(),
+ QualType ParamType;
+ if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ ParamType = (*P)->getType();
+ else
+ ParamType = (*P)->getOriginalType();
+ ParamType = ParamType.substObjCTypeArgs(Context, {},
+ ObjCSubstitutionContext::Parameter);
+ AddObjCPassingTypeChunk(ParamType,
(*P)->getObjCDeclQualifier(),
Context, Policy,
Builder);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index c6af2ed..99d4a79 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -128,45 +128,85 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
return false;
}
+namespace {
+enum class UnqualifiedTypeNameLookupResult {
+ NotFound,
+ FoundNonType,
+ FoundType
+};
+} // namespace
+
+/// \brief Tries to perform unqualified lookup of the type decls in bases for
+/// dependent class.
+/// \return \a NotFound if no any decls is found, \a FoundNotType if found not a
+/// type decl, \a FoundType if only type decls are found.
+static UnqualifiedTypeNameLookupResult
+lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II,
+ SourceLocation NameLoc,
+ const CXXRecordDecl *RD) {
+ if (!RD->hasDefinition())
+ return UnqualifiedTypeNameLookupResult::NotFound;
+ // Look for type decls in base classes.
+ UnqualifiedTypeNameLookupResult FoundTypeDecl =
+ UnqualifiedTypeNameLookupResult::NotFound;
+ for (const auto &Base : RD->bases()) {
+ const CXXRecordDecl *BaseRD = nullptr;
+ if (auto *BaseTT = Base.getType()->getAs<TagType>())
+ BaseRD = BaseTT->getAsCXXRecordDecl();
+ else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) {
+ // Look for type decls in dependent base classes that have known primary
+ // templates.
+ if (!TST || !TST->isDependentType())
+ continue;
+ auto *TD = TST->getTemplateName().getAsTemplateDecl();
+ if (!TD)
+ continue;
+ auto *BasePrimaryTemplate =
+ dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
+ if (!BasePrimaryTemplate)
+ continue;
+ BaseRD = BasePrimaryTemplate;
+ }
+ if (BaseRD) {
+ for (NamedDecl *ND : BaseRD->lookup(&II)) {
+ if (!isa<TypeDecl>(ND))
+ return UnqualifiedTypeNameLookupResult::FoundNonType;
+ FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+ }
+ if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) {
+ switch (lookupUnqualifiedTypeNameInBase(S, II, NameLoc, BaseRD)) {
+ case UnqualifiedTypeNameLookupResult::FoundNonType:
+ return UnqualifiedTypeNameLookupResult::FoundNonType;
+ case UnqualifiedTypeNameLookupResult::FoundType:
+ FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+ break;
+ case UnqualifiedTypeNameLookupResult::NotFound:
+ break;
+ }
+ }
+ }
+ }
+
+ return FoundTypeDecl;
+}
+
static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
const IdentifierInfo &II,
SourceLocation NameLoc) {
- // Find the first parent class template context, if any.
- // FIXME: Perform the lookup in all enclosing class templates.
+ // Lookup in the parent class template context, if any.
const CXXRecordDecl *RD = nullptr;
- for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) {
+ UnqualifiedTypeNameLookupResult FoundTypeDecl =
+ UnqualifiedTypeNameLookupResult::NotFound;
+ for (DeclContext *DC = S.CurContext;
+ DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound;
+ DC = DC->getParent()) {
+ // Look for type decls in dependent base classes that have known primary
+ // templates.
RD = dyn_cast<CXXRecordDecl>(DC);
if (RD && RD->getDescribedClassTemplate())
- break;
- }
- if (!RD)
- return ParsedType();
-
- // Look for type decls in dependent base classes that have known primary
- // templates.
- bool FoundTypeDecl = false;
- for (const auto &Base : RD->bases()) {
- auto *TST = Base.getType()->getAs<TemplateSpecializationType>();
- if (!TST || !TST->isDependentType())
- continue;
- auto *TD = TST->getTemplateName().getAsTemplateDecl();
- if (!TD)
- continue;
- auto *BasePrimaryTemplate =
- dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
- if (!BasePrimaryTemplate)
- continue;
- // FIXME: Allow lookup into non-dependent bases of dependent bases, possibly
- // by calling or integrating with the main LookupQualifiedName mechanism.
- for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
- if (FoundTypeDecl)
- return ParsedType();
- FoundTypeDecl = isa<TypeDecl>(ND);
- if (!FoundTypeDecl)
- return ParsedType();
- }
+ FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD);
}
- if (!FoundTypeDecl)
+ if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType)
return ParsedType();
// We found some types in dependent base classes. Recover as if the user
@@ -967,7 +1007,7 @@ Corrected:
// Check for a tag type hidden by a non-type decl in a few cases where it
// seems likely a type is wanted instead of the non-type that was found.
- bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
+ bool NextIsOp = NextToken.isOneOf(tok::amp, tok::star);
if ((NextToken.is(tok::identifier) ||
(NextIsOp &&
FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) &&
@@ -1041,6 +1081,22 @@ void Sema::PopDeclContext() {
assert(CurContext && "Popped translation unit!");
}
+Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S,
+ Decl *D) {
+ // Unlike PushDeclContext, the context to which we return is not necessarily
+ // the containing DC of TD, because the new context will be some pre-existing
+ // TagDecl definition instead of a fresh one.
+ auto Result = static_cast<SkippedDefinitionContext>(CurContext);
+ CurContext = cast<TagDecl>(D)->getDefinition();
+ assert(CurContext && "skipping definition of undefined tag");
+ S->setEntity(CurContext);
+ return Result;
+}
+
+void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) {
+ CurContext = static_cast<decltype(CurContext)>(Context);
+}
+
/// EnterDeclaratorContext - Used when we must lookup names in the context
/// of a declarator's nested name specifier.
///
@@ -1708,7 +1764,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Loc, Loc, II, R, /*TInfo=*/nullptr,
SC_Extern,
false,
- /*hasPrototype=*/true);
+ R->isFunctionProtoType());
New->setImplicit();
// Create Decl objects for each parameter, adding them to the
@@ -1744,11 +1800,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
/// should not consider because they are not permitted to conflict, e.g.,
/// because they come from hidden sub-modules and do not refer to the same
/// entity.
-static void filterNonConflictingPreviousDecls(ASTContext &context,
+static void filterNonConflictingPreviousDecls(Sema &S,
NamedDecl *decl,
LookupResult &previous){
// This is only interesting when modules are enabled.
- if (!context.getLangOpts().Modules)
+ if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) ||
+ !S.getLangOpts().ModulesHideInternalLinkage)
return;
// Empty sets are uninteresting.
@@ -1760,7 +1817,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context,
NamedDecl *old = filter.next();
// Non-hidden declarations are never ignored.
- if (!old->isHidden())
+ if (S.isVisible(old))
continue;
if (!old->isExternallyVisible())
@@ -1774,11 +1831,11 @@ static void filterNonConflictingPreviousDecls(ASTContext &context,
/// entity if their types are the same.
/// FIXME: This is notionally doing the same thing as ASTReaderDecl's
/// isSameEntity.
-static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context,
+static void filterNonConflictingPreviousTypedefDecls(Sema &S,
TypedefNameDecl *Decl,
LookupResult &Previous) {
// This is only interesting when modules are enabled.
- if (!Context.getLangOpts().Modules)
+ if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility)
return;
// Empty sets are uninteresting.
@@ -1790,16 +1847,23 @@ static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context,
NamedDecl *Old = Filter.next();
// Non-hidden declarations are never ignored.
- if (!Old->isHidden())
+ if (S.isVisible(Old))
continue;
// Declarations of the same entity are not ignored, even if they have
// different linkages.
- if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old))
- if (Context.hasSameType(OldTD->getUnderlyingType(),
- Decl->getUnderlyingType()))
+ if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) {
+ if (S.Context.hasSameType(OldTD->getUnderlyingType(),
+ Decl->getUnderlyingType()))
continue;
+ // If both declarations give a tag declaration a typedef name for linkage
+ // purposes, then they declare the same entity.
+ if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
+ Decl->getAnonDeclWithTypedefName())
+ continue;
+ }
+
if (!Old->isExternallyVisible())
Filter.erase();
}
@@ -1909,6 +1973,27 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
if (Old->isInvalidDecl())
return New->setInvalidDecl();
+ if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) {
+ auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true);
+ auto *NewTag = New->getAnonDeclWithTypedefName();
+ NamedDecl *Hidden = nullptr;
+ if (getLangOpts().CPlusPlus && OldTag && NewTag &&
+ OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() &&
+ !hasVisibleDefinition(OldTag, &Hidden)) {
+ // There is a definition of this tag, but it is not visible. Use it
+ // instead of our tag.
+ New->setTypeForDecl(OldTD->getTypeForDecl());
+ if (OldTD->isModed())
+ New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(),
+ OldTD->getUnderlyingType());
+ else
+ New->setTypeSourceInfo(OldTD->getTypeSourceInfo());
+
+ // Make the old tag definition visible.
+ makeMergedDefinitionVisible(Hidden, NewTag->getLocation());
+ }
+ }
+
// If the typedef types are not identical, reject them in all languages and
// with any extensions enabled.
if (isIncompatibleTypedef(Old, New))
@@ -1978,7 +2063,6 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
Diag(New->getLocation(), diag::ext_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return;
}
/// DeclhasAttr - returns true if decl Declaration already has the target
@@ -2382,6 +2466,33 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
if (!foundAny) newDecl->dropAttrs();
}
+static void mergeParamDeclTypes(ParmVarDecl *NewParam,
+ const ParmVarDecl *OldParam,
+ Sema &S) {
+ if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) {
+ if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) {
+ if (*Oldnullability != *Newnullability) {
+ S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr)
+ << DiagNullabilityKind(
+ *Newnullability,
+ ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ *Oldnullability,
+ ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
+ S.Diag(OldParam->getLocation(), diag::note_previous_declaration);
+ }
+ } else {
+ QualType NewT = NewParam->getType();
+ NewT = S.Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Oldnullability),
+ NewT, NewT);
+ NewParam->setType(NewT);
+ }
+ }
+}
+
namespace {
/// Used in MergeFunctionDecl to keep track of function parameters in
@@ -2466,6 +2577,48 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
return false;
}
+template<typename T> static bool isExternC(T *D) { return D->isExternC(); }
+static bool isExternC(VarTemplateDecl *) { return false; }
+
+/// \brief Check whether a redeclaration of an entity introduced by a
+/// using-declaration is valid, given that we know it's not an overload
+/// (nor a hidden tag declaration).
+template<typename ExpectedDecl>
+static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS,
+ ExpectedDecl *New) {
+ // C++11 [basic.scope.declarative]p4:
+ // Given a set of declarations in a single declarative region, each of
+ // which specifies the same unqualified name,
+ // -- they shall all refer to the same entity, or all refer to functions
+ // and function templates; or
+ // -- exactly one declaration shall declare a class name or enumeration
+ // name that is not a typedef name and the other declarations shall all
+ // refer to the same variable or enumerator, or all refer to functions
+ // and function templates; in this case the class name or enumeration
+ // name is hidden (3.3.10).
+
+ // C++11 [namespace.udecl]p14:
+ // If a function declaration in namespace scope or block scope has the
+ // same name and the same parameter-type-list as a function introduced
+ // by a using-declaration, and the declarations do not declare the same
+ // function, the program is ill-formed.
+
+ auto *Old = dyn_cast<ExpectedDecl>(OldS->getTargetDecl());
+ if (Old &&
+ !Old->getDeclContext()->getRedeclContext()->Equals(
+ New->getDeclContext()->getRedeclContext()) &&
+ !(isExternC(Old) && isExternC(New)))
+ Old = nullptr;
+
+ if (!Old) {
+ S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+ S.Diag(OldS->getTargetDecl()->getLocation(), diag::note_using_decl_target);
+ S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ return true;
+ }
+ return false;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2492,28 +2645,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
return true;
}
- // C++11 [namespace.udecl]p14:
- // If a function declaration in namespace scope or block scope has the
- // same name and the same parameter-type-list as a function introduced
- // by a using-declaration, and the declarations do not declare the same
- // function, the program is ill-formed.
-
// Check whether the two declarations might declare the same function.
- Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl());
- if (Old &&
- !Old->getDeclContext()->getRedeclContext()->Equals(
- New->getDeclContext()->getRedeclContext()) &&
- !(Old->isExternC() && New->isExternC()))
- Old = nullptr;
-
- if (!Old) {
- Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
- Diag(Shadow->getTargetDecl()->getLocation(),
- diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ if (checkUsingShadowRedecl<FunctionDecl>(*this, Shadow, New))
return true;
- }
- OldD = Old;
+ OldD = Old = cast<FunctionDecl>(Shadow->getTargetDecl());
} else {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -2643,7 +2778,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// UndefinedButUsed.
if (!Old->isInlined() && New->isInlined() &&
!New->hasAttr<GNUInlineAttr>() &&
- (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) &&
+ !getLangOpts().GNUInline &&
Old->isUsed(false) &&
!Old->isDefined() && !New->isThisDeclarationADefinition())
UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
@@ -2761,6 +2896,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
<< New << New->getType();
}
Diag(OldLocation, PrevDiag) << Old << Old->getType();
+ return true;
// Complain if this is an explicit declaration of a special
// member that was initially declared implicitly.
@@ -3017,9 +3153,12 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
// Merge attributes from the parameters. These can mismatch with K&R
// declarations.
if (New->getNumParams() == Old->getNumParams())
- for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
- mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
- *this);
+ for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
+ ParmVarDecl *NewParam = New->getParamDecl(i);
+ ParmVarDecl *OldParam = Old->getParamDecl(i);
+ mergeParamDeclAttributes(NewParam, OldParam, *this);
+ mergeParamDeclTypes(NewParam, OldParam, *this);
+ }
if (getLangOpts().CPlusPlus)
return MergeCXXFunctionDecl(New, Old, S);
@@ -3131,9 +3270,16 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
//
// Neither C nor C++ requires a diagnostic for this, but we should still try
// to diagnose it.
- Diag(New->getLocation(), diag::err_redefinition_different_type)
- << New->getDeclName() << New->getType() << Old->getType();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(New->getLocation(), New->isThisDeclarationADefinition()
+ ? diag::err_redefinition_different_type
+ : diag::err_redeclaration_different_type)
+ << New->getDeclName() << New->getType() << Old->getType();
+
+ diag::kind PrevDiag;
+ SourceLocation OldLocation;
+ std::tie(PrevDiag, OldLocation) =
+ getNoteDiagForInvalidRedeclaration(Old, New);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
@@ -3194,8 +3340,19 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (NewTemplate) {
OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr;
- } else
+
+ if (auto *Shadow =
+ dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl()))
+ if (checkUsingShadowRedecl<VarTemplateDecl>(*this, Shadow, NewTemplate))
+ return New->setInvalidDecl();
+ } else {
Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
+
+ if (auto *Shadow =
+ dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl()))
+ if (checkUsingShadowRedecl<VarDecl>(*this, Shadow, New))
+ return New->setInvalidDecl();
+ }
}
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
@@ -3336,14 +3493,24 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
// C++ doesn't have tentative definitions, so go right ahead and check here.
- const VarDecl *Def;
+ VarDecl *Def;
if (getLangOpts().CPlusPlus &&
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
- Diag(New->getLocation(), diag::err_redefinition) << New;
- Diag(Def->getLocation(), diag::note_previous_definition);
- New->setInvalidDecl();
- return;
+ NamedDecl *Hidden = nullptr;
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (New->getFormalLinkage() == InternalLinkage ||
+ New->getDescribedVarTemplate() ||
+ New->getNumTemplateParameterLists() ||
+ New->getDeclContext()->isDependentContext())) {
+ // The previous definition is hidden, and multiple definitions are
+ // permitted (in separate TUs). Form another definition of it.
+ } else {
+ Diag(New->getLocation(), diag::err_redefinition) << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
@@ -3375,8 +3542,20 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
-static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) {
- if (!S.Context.getLangOpts().CPlusPlus)
+// The MS ABI changed between VS2013 and VS2015 with regard to numbers used to
+// disambiguate entities defined in different scopes.
+// While the VS2015 ABI fixes potential miscompiles, it is also breaks
+// compatibility.
+// We will pick our mangling number depending on which version of MSVC is being
+// targeted.
+static unsigned getMSManglingNumber(const LangOptions &LO, Scope *S) {
+ return LO.isCompatibleWithMSVC(LangOptions::MSVC2015)
+ ? S->getMSCurManglingNumber()
+ : S->getMSLastManglingNumber();
+}
+
+void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) {
+ if (!Context.getLangOpts().CPlusPlus)
return;
if (isa<CXXRecordDecl>(Tag->getParent())) {
@@ -3385,20 +3564,78 @@ static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) {
if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl())
return;
MangleNumberingContext &MCtx =
- S.Context.getManglingNumberContext(Tag->getParent());
- S.Context.setManglingNumber(
- Tag, MCtx.getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
+ Context.getManglingNumberContext(Tag->getParent());
+ Context.setManglingNumber(
+ Tag, MCtx.getManglingNumber(
+ Tag, getMSManglingNumber(getLangOpts(), TagScope)));
return;
}
// If this tag isn't a direct child of a class, number it if it is local.
Decl *ManglingContextDecl;
- if (MangleNumberingContext *MCtx =
- S.getCurrentMangleNumberContext(Tag->getDeclContext(),
- ManglingContextDecl)) {
- S.Context.setManglingNumber(
- Tag,
- MCtx->getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
+ if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext(
+ Tag->getDeclContext(), ManglingContextDecl)) {
+ Context.setManglingNumber(
+ Tag, MCtx->getManglingNumber(
+ Tag, getMSManglingNumber(getLangOpts(), TagScope)));
+ }
+}
+
+void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
+ TypedefNameDecl *NewTD) {
+ // Do nothing if the tag is not anonymous or already has an
+ // associated typedef (from an earlier typedef in this decl group).
+ if (TagFromDeclSpec->getIdentifier())
+ return;
+ if (TagFromDeclSpec->getTypedefNameForAnonDecl())
+ return;
+
+ // A well-formed anonymous tag must always be a TUK_Definition.
+ assert(TagFromDeclSpec->isThisDeclarationADefinition());
+
+ // The type must match the tag exactly; no qualifiers allowed.
+ if (!Context.hasSameType(NewTD->getUnderlyingType(),
+ Context.getTagDeclType(TagFromDeclSpec)))
+ return;
+
+ // If we've already computed linkage for the anonymous tag, then
+ // adding a typedef name for the anonymous decl can change that
+ // linkage, which might be a serious problem. Diagnose this as
+ // unsupported and ignore the typedef name. TODO: we should
+ // pursue this as a language defect and establish a formal rule
+ // for how to handle it.
+ if (TagFromDeclSpec->hasLinkageBeenComputed()) {
+ Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage);
+
+ SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart();
+ tagLoc = getLocForEndOfToken(tagLoc);
+
+ llvm::SmallString<40> textToInsert;
+ textToInsert += ' ';
+ textToInsert += NewTD->getIdentifier()->getName();
+ Diag(tagLoc, diag::note_typedef_changes_linkage)
+ << FixItHint::CreateInsertion(tagLoc, textToInsert);
+ return;
+ }
+
+ // Otherwise, set this is the anon-decl typedef for the tag.
+ TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
+}
+
+static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
+ switch (T) {
+ case DeclSpec::TST_class:
+ return 0;
+ case DeclSpec::TST_struct:
+ return 1;
+ case DeclSpec::TST_interface:
+ return 2;
+ case DeclSpec::TST_union:
+ return 3;
+ case DeclSpec::TST_enum:
+ return 4;
+ default:
+ llvm_unreachable("unexpected type specifier");
}
}
@@ -3431,7 +3668,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
- HandleTagNumbering(*this, Tag, S);
+ handleTagNumbering(Tag, S);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -3451,10 +3688,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// and definitions of functions and variables.
if (Tag)
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
- << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
- DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
- DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
- DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4);
+ << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType());
else
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
// Don't emit warnings after this error.
@@ -3471,7 +3705,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
- CXXScopeSpec &SS = DS.getTypeSpecScope();
+ const CXXScopeSpec &SS = DS.getTypeSpecScope();
bool IsExplicitSpecialization =
!TemplateParams.empty() && TemplateParams.back()->size() == 0;
if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
@@ -3481,11 +3715,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// or an explicit specialization.
// Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
- << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
- DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
- DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
- DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
- << SS.getRange();
+ << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
return nullptr;
}
@@ -3498,7 +3728,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOpts().CPlusPlus ||
Record->getDeclContext()->isRecord())
- return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy());
+ return BuildAnonymousStructOrUnion(S, DS, AS, Record,
+ Context.getPrintingPolicy());
DeclaresAnything = false;
}
@@ -3632,16 +3863,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
TypeSpecType == DeclSpec::TST_interface ||
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
- AttributeList* attrs = DS.getAttributes().getList();
- while (attrs) {
+ for (AttributeList* attrs = DS.getAttributes().getList(); attrs;
+ attrs = attrs->getNext())
Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored)
- << attrs->getName()
- << (TypeSpecType == DeclSpec::TST_class ? 0 :
- TypeSpecType == DeclSpec::TST_struct ? 1 :
- TypeSpecType == DeclSpec::TST_union ? 2 :
- TypeSpecType == DeclSpec::TST_interface ? 3 : 4);
- attrs = attrs->getNext();
- }
+ << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
}
}
@@ -3726,8 +3951,7 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
// anonymous union is declared.
unsigned OldChainingSize = Chaining.size();
if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
- for (auto *PI : IF->chain())
- Chaining.push_back(PI);
+ Chaining.append(IF->chain_begin(), IF->chain_end());
else
Chaining.push_back(VD);
@@ -4054,10 +4278,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (VarDecl *NewVD = dyn_cast<VarDecl>(Anon)) {
if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
Decl *ManglingContextDecl;
- if (MangleNumberingContext *MCtx =
- getCurrentMangleNumberContext(NewVD->getDeclContext(),
- ManglingContextDecl)) {
- Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext(
+ NewVD->getDeclContext(), ManglingContextDecl)) {
+ Context.setManglingNumber(
+ NewVD, MCtx->getManglingNumber(
+ NewVD, getMSManglingNumber(getLangOpts(), S)));
Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
}
}
@@ -4532,12 +4757,14 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
return nullptr;
+ // If a class is incomplete, do not parse entities inside it.
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
Diag(D.getIdentifierLoc(),
diag::err_member_def_undefined_record)
<< Name << DC << D.getCXXScopeSpec().getRange();
- D.setInvalidType();
- } else if (!D.getDeclSpec().isFriendSpecified()) {
+ return nullptr;
+ }
+ if (!D.getDeclSpec().isFriendSpecified()) {
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
Name, D.getIdentifierLoc())) {
if (DC->isRecord())
@@ -4557,15 +4784,16 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
}
}
- if (DiagnoseClassNameShadow(DC, NameInfo))
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType R = TInfo->getType();
+
+ if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
// If this is a typedef, we'll end up spewing multiple diagnostics.
- // Just return early; it's safer.
+ // Just return early; it's safer. If this is a function, let the
+ // "constructor cannot have a return type" diagnostic handle it.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return nullptr;
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType R = TInfo->getType();
-
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
@@ -4767,6 +4995,8 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
static void
FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
+ SrcTL = SrcTL.getUnqualifiedLoc();
+ DstTL = DstTL.getUnqualifiedLoc();
if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) {
PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>();
FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(),
@@ -4823,27 +5053,13 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
return;
// Note that we have a locally-scoped external with this name.
- // FIXME: There can be multiple such declarations if they are functions marked
- // __attribute__((overloadable)) declared in function scope in C.
- LocallyScopedExternCDecls[ND->getDeclName()] = ND;
+ Context.getExternCContextDecl()->makeDeclVisibleInContext(ND);
}
NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
- if (ExternalSource) {
- // Load locally-scoped external decls from the external source.
- // FIXME: This is inefficient. Maybe add a DeclContext for extern "C" decls?
- SmallVector<NamedDecl *, 4> Decls;
- ExternalSource->ReadLocallyScopedExternCDecls(Decls);
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = LocallyScopedExternCDecls.find(Decls[I]->getDeclName());
- if (Pos == LocallyScopedExternCDecls.end())
- LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
- }
- }
-
- NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
- return D ? D->getMostRecentDecl() : nullptr;
+ // FIXME: We can have multiple results via __attribute__((overloadable)).
+ auto Result = Context.getExternCContextDecl()->lookup(Name);
+ return Result.empty() ? nullptr : *Result.begin();
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
@@ -4955,7 +5171,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
// in an outer scope, it isn't the same thing.
FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false,
/*AllowInlineNamespace*/false);
- filterNonConflictingPreviousTypedefDecls(Context, NewTD, Previous);
+ filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
@@ -5102,14 +5318,27 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
if (ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
ND.dropAttr<WeakRefAttr>();
+ ND.dropAttr<AliasAttr>();
}
}
- // 'selectany' only applies to externally visible varable declarations.
+ if (auto *VD = dyn_cast<VarDecl>(&ND)) {
+ if (VD->hasInit()) {
+ if (const auto *Attr = VD->getAttr<AliasAttr>()) {
+ assert(VD->isThisDeclarationADefinition() &&
+ !VD->isExternallyVisible() && "Broken AliasAttr handled late!");
+ S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD;
+ VD->dropAttr<AliasAttr>();
+ }
+ }
+ }
+
+ // 'selectany' only applies to externally visible variable declarations.
// It does not apply to functions.
if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) {
if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) {
- S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data);
+ S.Diag(Attr->getLocation(),
+ diag::err_attribute_selectany_non_extern_data);
ND.dropAttr<SelectAnyAttr>();
}
}
@@ -5339,6 +5568,19 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
+/// \brief Returns true if given declaration is TU-scoped and externally
+/// visible.
+static bool isDeclTUScopedExternallyVisible(const Decl *D) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ return (FD->getDeclContext()->isTranslationUnit() || FD->isExternC()) &&
+ FD->hasExternalFormalLinkage();
+ else if (auto *VD = dyn_cast<VarDecl>(D))
+ return (VD->getDeclContext()->isTranslationUnit() || VD->isExternC()) &&
+ VD->hasExternalFormalLinkage();
+
+ llvm_unreachable("Unknown type of decl!");
+}
+
NamedDecl *
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -5565,8 +5807,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
} else {
- assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
- "should have a 'template<>' for this decl");
+ assert(
+ (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) &&
+ "should have a 'template<>' for this decl");
}
if (IsVariableTemplateSpecialization) {
@@ -5627,6 +5870,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (IsLocalExternDecl)
NewVD->setLocalExternDecl();
+ bool EmitTLSUnsupportedError = false;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
// C++11 [dcl.stc]p4:
// When thread_local is applied to a variable of block scope the
@@ -5641,10 +5885,20 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS);
- else if (!Context.getTargetInfo().isTLSSupported())
- Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
- diag::err_thread_unsupported);
- else
+ else if (!Context.getTargetInfo().isTLSSupported()) {
+ if (getLangOpts().CUDA) {
+ // Postpone error emission until we've collected attributes required to
+ // figure out whether it's a host or device variable and whether the
+ // error should be ignored.
+ EmitTLSUnsupportedError = true;
+ // We still need to mark the variable as TLS so it shows up in AST with
+ // proper storage class for other tools to use even if we're not going
+ // to emit any code for it.
+ NewVD->setTSCSpec(TSCS);
+ } else
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_thread_unsupported);
+ } else
NewVD->setTSCSpec(TSCS);
}
@@ -5693,6 +5947,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
ProcessDeclAttributes(S, NewVD, D);
if (getLangOpts().CUDA) {
+ if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD))
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_thread_unsupported);
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
if (SC == SC_None && S->getFnParent() != nullptr &&
@@ -5748,7 +6005,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, Label, 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty() &&
+ isDeclTUScopedExternallyVisible(NewVD)) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
@@ -5845,11 +6103,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
Decl *ManglingContextDecl;
- if (MangleNumberingContext *MCtx =
- getCurrentMangleNumberContext(NewVD->getDeclContext(),
- ManglingContextDecl)) {
+ if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext(
+ NewVD->getDeclContext(), ManglingContextDecl)) {
Context.setManglingNumber(
- NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ NewVD, MCtx->getManglingNumber(
+ NewVD, getMSManglingNumber(getLangOpts(), S)));
Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
}
}
@@ -6243,7 +6501,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
Previous.setShadowed();
// Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(Context, NewVD, Previous);
+ filterNonConflictingPreviousDecls(*this, NewVD, Previous);
if (!Previous.empty()) {
MergeVarDecl(NewVD, Previous);
@@ -6898,8 +7156,10 @@ static void checkIsValidOpenCLKernelParameter(
// We have an error, now let's go back up through history and show where
// the offending field came from
- for (ArrayRef<const FieldDecl *>::const_iterator I = HistoryStack.begin() + 1,
- E = HistoryStack.end(); I != E; ++I) {
+ for (ArrayRef<const FieldDecl *>::const_iterator
+ I = HistoryStack.begin() + 1,
+ E = HistoryStack.end();
+ I != E; ++I) {
const FieldDecl *OuterField = *I;
S.Diag(OuterField->getLocation(), diag::note_within_field_of_type)
<< OuterField->getType();
@@ -6985,6 +7245,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
dyn_cast<CXXRecordDecl>(NewFD->getDeclContext())) {
if (Parent->isInterface() && cast<CXXMethodDecl>(NewFD)->isUserProvided())
NewFD->setPure(true);
+
+ // C++ [class.union]p2
+ // A union can have member functions, but not virtual functions.
+ if (isVirtual && Parent->isUnion())
+ Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union);
}
SetNestedNameSpecifier(NewFD, D);
@@ -7010,12 +7275,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
- return nullptr;
+ NewFD->setInvalidDecl();
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
- return nullptr;
+ NewFD->setInvalidDecl();
}
// If we're adding a template to a dependent context, we may need to
@@ -7268,7 +7533,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString(), 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty() &&
+ isDeclTUScopedExternallyVisible(NewFD)) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
@@ -7347,7 +7613,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setInvalidDecl();
}
- if (D.isFunctionDefinition() && CodeSegStack.CurrentValue &&
+ // Apply an implicit SectionAttr if #pragma code_seg is active.
+ if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
!NewFD->hasAttr<SectionAttr>()) {
NewFD->addAttr(
SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
@@ -7363,23 +7630,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
- QualType RetType = NewFD->getReturnType();
- const CXXRecordDecl *Ret = RetType->isRecordType() ?
- RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
- if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
- Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- // Attach WarnUnusedResult to functions returning types with that attribute.
- // Don't apply the attribute to that type's own non-static member functions
- // (to avoid warning on things like assignment operators)
- if (!MD || MD->getParent() != Ret)
- NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
- }
-
if (getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5: Using an address space qualifier in a function return
// type declaration will generate a compilation error.
- unsigned AddressSpace = RetType.getAddressSpace();
+ unsigned AddressSpace = NewFD->getReturnType().getAddressSpace();
if (AddressSpace == LangAS::opencl_local ||
AddressSpace == LangAS::opencl_global ||
AddressSpace == LangAS::opencl_constant) {
@@ -7402,7 +7656,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
else if (!Previous.empty())
- // Make graceful recovery from an invalid redeclaration.
+ // Recover gracefully from an invalid redeclaration.
D.setRedeclaration(true);
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
@@ -7543,6 +7797,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!NewFD->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
+ else if (!Previous.empty())
+ // Recover gracefully from an invalid redeclaration.
+ D.setRedeclaration(true);
}
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
@@ -7799,7 +8056,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
!Previous.isShadowed();
// Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+ filterNonConflictingPreviousDecls(*this, NewFD, Previous);
bool Redeclaration = false;
NamedDecl *OldDecl = nullptr;
@@ -7854,7 +8111,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// Check for a previous extern "C" declaration with this name.
if (!Redeclaration &&
checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
- filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+ filterNonConflictingPreviousDecls(*this, NewFD, Previous);
if (!Previous.empty()) {
// This is an extern "C" declaration with the same name as a previous
// declaration, and thus redeclares that entity...
@@ -7952,28 +8209,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// This needs to happen first so that 'inline' propagates.
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
- if (isa<CXXMethodDecl>(NewFD)) {
- // A valid redeclaration of a C++ method must be out-of-line,
- // but (unfortunately) it's not necessarily a definition
- // because of templates, which means that the previous
- // declaration is not necessarily from the class definition.
-
- // For just setting the access, that doesn't matter.
- CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl);
- NewFD->setAccess(oldMethod->getAccess());
-
- // Update the key-function state if necessary for this ABI.
- if (NewFD->isInlined() &&
- !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
- // setNonKeyFunction needs to work with the original
- // declaration from the class definition, and isVirtual() is
- // just faster in that case, so map back to that now.
- oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl());
- if (oldMethod->isVirtual()) {
- Context.setNonKeyFunction(oldMethod);
- }
- }
- }
+ if (isa<CXXMethodDecl>(NewFD))
+ NewFD->setAccess(OldDecl->getAccess());
}
}
@@ -8153,6 +8390,12 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
bool HasExtraParameters = (nparams > 3);
+ if (FTP->isVariadic()) {
+ Diag(FD->getLocation(), diag::ext_variadic_main);
+ // FIXME: if we had information about the location of the ellipsis, we
+ // could add a FixIt hint to remove it as a parameter.
+ }
+
// Darwin passes an undocumented fourth argument of type char**. If
// other platforms start sprouting these, the logic below will start
// getting shifty.
@@ -8543,8 +8786,13 @@ namespace {
diag = diag::warn_uninit_self_reference_in_reference_init;
} else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) {
diag = diag::warn_static_self_reference_in_init;
- } else {
+ } else if (isa<TranslationUnitDecl>(OrigDecl->getDeclContext()) ||
+ isa<NamespaceDecl>(OrigDecl->getDeclContext()) ||
+ DRE->getDecl()->getType()->isRecordType()) {
diag = diag::warn_uninit_self_reference_in_init;
+ } else {
+ // Local variables will be handled by the CFG analysis.
+ return;
}
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
@@ -8586,23 +8834,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
if (!RealDecl || RealDecl->isInvalidDecl()) {
- CorrectDelayedTyposInExpr(Init);
+ CorrectDelayedTyposInExpr(Init, dyn_cast_or_null<VarDecl>(RealDecl));
return;
}
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
- // With declarators parsed the way they are, the parser cannot
- // distinguish between a normal initializer and a pure-specifier.
- // Thus this grotesque test.
- IntegerLiteral *IL;
- if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
- Context.getCanonicalType(IL->getType()) == Context.IntTy)
- CheckPureMethod(Method, Init->getSourceRange());
- else {
- Diag(Method->getLocation(), diag::err_member_function_initialization)
- << Method->getDeclName() << Init->getSourceRange();
- Method->setInvalidDecl();
- }
+ // Pure-specifiers are handled in ActOnPureSpecifier.
+ Diag(Method->getLocation(), diag::err_member_function_initialization)
+ << Method->getDeclName() << Init->getSourceRange();
+ Method->setInvalidDecl();
return;
}
@@ -8617,6 +8857,21 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
+ // Attempt typo correction early so that the type of the init expression can
+ // be deduced based on the chosen correction:if the original init contains a
+ // TypoExpr.
+ ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
+ if (!Res.isUsable()) {
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
+ if (Res.get() != Init) {
+ Init = Res.get();
+ if (CXXDirectInit)
+ CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+ }
+
Expr *DeduceInit = Init;
// Initializer could be a C++ direct-initializer. Deduction only works if it
// contains exactly one expression.
@@ -8746,16 +9001,25 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
}
- const VarDecl *Def;
+ VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- VDecl->setInvalidDecl();
- return;
+ NamedDecl *Hidden = nullptr;
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (VDecl->getFormalLinkage() == InternalLinkage ||
+ VDecl->getDescribedVarTemplate() ||
+ VDecl->getNumTemplateParameterLists() ||
+ VDecl->getDeclContext()->isDependentContext())) {
+ // The previous definition is hidden, and multiple definitions are
+ // permitted (in separate TUs). Form another definition of it.
+ } else {
+ Diag(VDecl->getLocation(), diag::err_redefinition)
+ << VDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
}
- const VarDecl *PrevInit = nullptr;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
// If a static data member is of const integral or const
@@ -8769,10 +9033,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// We already performed a redefinition check above, but for static
// data members we also need to check whether there was an in-class
// declaration with an initializer.
- if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ if (VDecl->isStaticDataMember() && VDecl->getCanonicalDecl()->hasInit()) {
Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization)
<< VDecl->getDeclName();
- Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0;
+ Diag(VDecl->getCanonicalDecl()->getInit()->getExprLoc(),
+ diag::note_previous_initializer)
+ << 0;
return;
}
@@ -8829,8 +9095,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// Try to correct any TypoExprs in the initialization arguments.
for (size_t Idx = 0; Idx < Args.size(); ++Idx) {
- ExprResult Res =
- CorrectDelayedTyposInExpr(Args[Idx], [this, Entity, Kind](Expr *E) {
+ ExprResult Res = CorrectDelayedTyposInExpr(
+ Args[Idx], VDecl, [this, Entity, Kind](Expr *E) {
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
return Init.Failed() ? ExprError() : E;
});
@@ -9253,6 +9519,8 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
Var->setInvalidDecl();
return;
}
+ } else {
+ return;
}
// The variable can not have an abstract class type.
@@ -9350,8 +9618,6 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
case SC_OpenCLWorkGroupLocal:
llvm_unreachable("Unexpected storage class");
}
- if (VD->isConstexpr())
- Error = 5;
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
<< VD->getDeclName() << Error;
@@ -9453,7 +9719,9 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
- if (var->isThisDeclarationADefinition() &&
+ // Apply section attributes and pragmas to global variables.
+ bool GlobalStorage = var->hasGlobalStorage();
+ if (GlobalStorage && var->isThisDeclarationADefinition() &&
ActiveTemplateInstantiations.empty()) {
PragmaStack<StringLiteral *> *Stack = nullptr;
int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
@@ -9466,11 +9734,11 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Stack = &DataSegStack;
SectionFlags |= ASTContext::PSF_Write;
}
- if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
- var->addAttr(
- SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
- Stack->CurrentValue->getString(),
- Stack->CurrentPragmaLocation));
+ if (Stack->CurrentValue && !var->hasAttr<SectionAttr>()) {
+ var->addAttr(SectionAttr::CreateImplicit(
+ Context, SectionAttr::Declspec_allocate,
+ Stack->CurrentValue->getString(), Stack->CurrentPragmaLocation));
+ }
if (const SectionAttr *SA = var->getAttr<SectionAttr>())
if (UnifySection(SA->getName(), SectionFlags, var))
var->dropAttr<SectionAttr>();
@@ -9513,7 +9781,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
Expr *Init = var->getInit();
- bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
+ bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
if (!var->getDeclContext()->isDependentContext() &&
@@ -9560,6 +9828,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
FinalizeVarWithDestructor(var, recordType);
}
+/// \brief Determines if a variable's alignment is dependent.
+static bool hasDependentAlignment(VarDecl *VD) {
+ if (VD->getType()->isDependentType())
+ return true;
+ for (auto *I : VD->specific_attrs<AlignedAttr>())
+ if (I->isAlignmentDependent())
+ return true;
+ return false;
+}
+
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached.
void
@@ -9573,6 +9851,22 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
checkAttributesAfterMerging(*this, *VD);
+ // Perform TLS alignment check here after attributes attached to the variable
+ // which may affect the alignment have been processed. Only perform the check
+ // if the target has a maximum TLS alignment (zero means no constraints).
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ // Protect the check so that it's not performed on dependent types and
+ // dependent alignments (we can't determine the alignment in that case).
+ if (VD->getTLSKind() && !hasDependentAlignment(VD)) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Context.getDeclAlign(VD) > MaxAlignChars) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ }
+ }
+ }
+
// Static locals inherit dll attributes from their function.
if (VD->isStaticLocal()) {
if (FunctionDecl *FD =
@@ -9625,18 +9919,6 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
- if (!VD->isInvalidDecl() &&
- VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) {
- if (const VarDecl *Def = VD->getDefinition()) {
- if (Def->hasAttr<AliasAttr>()) {
- Diag(VD->getLocation(), diag::err_tentative_after_alias)
- << VD->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- VD->setInvalidDecl();
- }
- }
- }
-
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this variable.
@@ -9699,7 +9981,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
- HandleTagNumbering(*this, Tag, S);
+ handleTagNumbering(Tag, S);
if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
}
@@ -9766,9 +10048,12 @@ void Sema::ActOnDocumentableDecl(Decl *D) {
void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) {
// Don't parse the comment if Doxygen diagnostics are ignored.
if (Group.empty() || !Group[0])
- return;
+ return;
- if (Diags.isIgnored(diag::warn_doc_param_not_found, Group[0]->getLocation()))
+ if (Diags.isIgnored(diag::warn_doc_param_not_found,
+ Group[0]->getLocation()) &&
+ Diags.isIgnored(diag::warn_unknown_comment_command_name,
+ Group[0]->getLocation()))
return;
if (Group.size() >= 2) {
@@ -10058,7 +10343,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
<< " int " << FTI.Params[i].Ident->getName() << ";\n";
Diag(FTI.Params[i].IdentLoc, diag::ext_param_not_declared)
<< FTI.Params[i].Ident
- << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
+ << FixItHint::CreateInsertion(LocAfterDecls, Code);
// Implicitly declare the argument as type 'int' for lack of a better
// type.
@@ -10127,6 +10412,10 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
if (FD->hasAttr<OpenCLKernelAttr>())
return false;
+ // Don't warn on explicitly deleted functions.
+ if (FD->isDeleted())
+ return false;
+
bool MissingPrototype = true;
for (const FunctionDecl *Prev = FD->getPreviousDecl();
Prev; Prev = Prev->getPreviousDecl()) {
@@ -10157,6 +10446,19 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
if (canRedefineFunction(Definition, getLangOpts()))
return;
+ // If we don't have a visible definition of the function, and it's inline or
+ // a template, it's OK to form another definition of it.
+ //
+ // FIXME: Should we skip the body of the function and use the old definition
+ // in this case? That may be necessary for functions that return local types
+ // through a deduced return type, or instantiate templates with local types.
+ if (!hasVisibleDefinition(Definition) &&
+ (Definition->getFormalLinkage() == InternalLinkage ||
+ Definition->isInlined() ||
+ Definition->getDescribedFunctionTemplate() ||
+ Definition->getNumTemplateParameterLists()))
+ return;
+
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
@@ -10269,30 +10571,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
diag::err_func_def_incomplete_result))
FD->setInvalidDecl();
- // GNU warning -Wmissing-prototypes:
- // Warn if a global function is defined without a previous
- // prototype declaration. This warning is issued even if the
- // definition itself provides a prototype. The aim is to detect
- // global functions that fail to be declared in header files.
- const FunctionDecl *PossibleZeroParamPrototype = nullptr;
- if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
- Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
-
- if (PossibleZeroParamPrototype) {
- // We found a declaration that is not a prototype,
- // but that could be a zero-parameter prototype
- if (TypeSourceInfo *TI =
- PossibleZeroParamPrototype->getTypeSourceInfo()) {
- TypeLoc TL = TI->getTypeLoc();
- if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
- Diag(PossibleZeroParamPrototype->getLocation(),
- diag::note_declaration_not_a_prototype)
- << PossibleZeroParamPrototype
- << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
- }
- }
- }
-
if (FnBodyScope)
PushDeclContext(FnBodyScope, FD);
@@ -10321,9 +10599,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
I != E; ++I) {
NamedDecl *D = *I;
- // Some of these decls (like enums) may have been pinned to the translation unit
- // for lack of a real context earlier. If so, remove from the translation unit
- // and reattach to the current context.
+ // Some of these decls (like enums) may have been pinned to the
+ // translation unit for lack of a real context earlier. If so, remove
+ // from the translation unit and reattach to the current context.
if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
// Is the decl actually in the context?
for (const auto *DI : Context.getTranslationUnitDecl()->decls()) {
@@ -10468,6 +10746,23 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
Context.adjustDeducedFunctionResultType(
FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
+ } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) {
+ auto *LSI = getCurLambda();
+ if (LSI->HasImplicitReturnType) {
+ deduceClosureReturnType(*LSI);
+
+ // C++11 [expr.prim.lambda]p4:
+ // [...] if there are no return statements in the compound-statement
+ // [the deduced type is] the type void
+ QualType RetType =
+ LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType;
+
+ // Update the return type to the deduced type.
+ const FunctionProtoType *Proto =
+ FD->getType()->getAs<FunctionProtoType>();
+ FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(),
+ Proto->getExtProtoInfo()));
+ }
}
// The only way to be included in UndefinedButUsed is if there is an
@@ -10477,7 +10772,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!FD->isExternallyVisible())
UndefinedButUsed.erase(FD);
else if (FD->isInlined() &&
- (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+ !LangOpts.GNUInline &&
(!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
UndefinedButUsed.erase(FD);
}
@@ -10494,7 +10789,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!FD->isInvalidDecl()) {
// Don't diagnose unused parameters of defaulted or deleted functions.
- if (Body)
+ if (!FD->isDeleted() && !FD->isDefaulted())
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
FD->getReturnType(), FD);
@@ -10512,7 +10807,55 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
!FD->isDependentContext())
computeNRVO(Body, getCurFunction());
}
-
+
+ // GNU warning -Wmissing-prototypes:
+ // Warn if a global function is defined without a previous
+ // prototype declaration. This warning is issued even if the
+ // definition itself provides a prototype. The aim is to detect
+ // global functions that fail to be declared in header files.
+ const FunctionDecl *PossibleZeroParamPrototype = nullptr;
+ if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
+ Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+ if (PossibleZeroParamPrototype) {
+ // We found a declaration that is not a prototype,
+ // but that could be a zero-parameter prototype
+ if (TypeSourceInfo *TI =
+ PossibleZeroParamPrototype->getTypeSourceInfo()) {
+ TypeLoc TL = TI->getTypeLoc();
+ if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
+ Diag(PossibleZeroParamPrototype->getLocation(),
+ diag::note_declaration_not_a_prototype)
+ << PossibleZeroParamPrototype
+ << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ }
+ }
+ }
+
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXMethodDecl *KeyFunction;
+ if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
+ MD->isVirtual() &&
+ (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) &&
+ MD == KeyFunction->getCanonicalDecl()) {
+ // Update the key-function state if necessary for this ABI.
+ if (FD->isInlined() &&
+ !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ Context.setNonKeyFunction(MD);
+
+ // If the newly-chosen key function is already defined, then we
+ // need to mark the vtable as used retroactively.
+ KeyFunction = Context.getCurrentKeyFunction(MD->getParent());
+ const FunctionDecl *Definition;
+ if (KeyFunction && KeyFunction->isDefined(Definition))
+ MarkVTableUsed(Definition->getLocation(), MD->getParent(), true);
+ } else {
+ // We just defined they key function; mark the vtable as used.
+ MarkVTableUsed(FD->getLocation(), MD->getParent(), true);
+ }
+ }
+ }
+
assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
"Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
@@ -10561,7 +10904,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (getCurFunction()->ObjCWarnForNoInitDelegation) {
// Don't issue this warning for unavaialable inits.
if (!MD->isUnavailable())
- Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
+ Diag(MD->getLocation(),
+ diag::warn_objc_secondary_init_missing_init_call);
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
@@ -10573,7 +10917,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
"handled in the block above.");
// Verify and clean out per-function state.
- if (Body) {
+ if (Body && (!FD || !FD->isDefaulted())) {
// C++ constructors that have function-try-blocks can't have return
// statements in the handlers of that block. (C++ [except.handle]p14)
// Verify this.
@@ -10623,8 +10967,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}
- assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects
- && "Leftover temporaries in function");
+ assert(ExprCleanupObjects.size() ==
+ ExprEvalContexts.back().NumCleanupObjects &&
+ "Leftover temporaries in function");
assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
assert(MaybeODRUseExprs.empty() &&
"Leftover expressions for odr-use checking");
@@ -10888,44 +11233,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
case TST_union:
case TST_class: {
TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
-
- // Do nothing if the tag is not anonymous or already has an
- // associated typedef (from an earlier typedef in this decl group).
- if (tagFromDeclSpec->getIdentifier()) break;
- if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break;
-
- // A well-formed anonymous tag must always be a TUK_Definition.
- assert(tagFromDeclSpec->isThisDeclarationADefinition());
-
- // The type must match the tag exactly; no qualifiers allowed.
- if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
- break;
-
- // If we've already computed linkage for the anonymous tag, then
- // adding a typedef name for the anonymous decl can change that
- // linkage, which might be a serious problem. Diagnose this as
- // unsupported and ignore the typedef name. TODO: we should
- // pursue this as a language defect and establish a formal rule
- // for how to handle it.
- if (tagFromDeclSpec->hasLinkageBeenComputed()) {
- Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage);
-
- SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- tagLoc = getLocForEndOfToken(tagLoc);
-
- llvm::SmallString<40> textToInsert;
- textToInsert += ' ';
- textToInsert += D.getIdentifier()->getName();
- Diag(tagLoc, diag::note_typedef_changes_linkage)
- << FixItHint::CreateInsertion(tagLoc, textToInsert);
- break;
- }
-
- // Otherwise, set this is the anon-decl typedef for the tag.
- tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
+ setTagNameForLinkagePurposes(tagFromDeclSpec, NewTD);
break;
}
-
+
default:
break;
}
@@ -11016,7 +11327,7 @@ static bool isClassCompatTagKind(TagTypeKind Tag)
bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
- const IdentifierInfo &Name) {
+ const IdentifierInfo *Name) {
// C++ [dcl.type.elab]p3:
// The class-key or enum keyword present in the
// elaborated-type-specifier shall agree in kind with the
@@ -11045,7 +11356,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
// In a template instantiation, do not offer fix-its for tag mismatches
// since they usually mess up the template instead of fixing the problem.
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
return true;
}
@@ -11064,7 +11375,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
if (!previousMismatch) {
previousMismatch = true;
Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(I->getTagKind());
}
Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
@@ -11086,7 +11397,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
}
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
@@ -11146,13 +11457,37 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
-/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the
+/// \brief Determine whether a tag originally declared in context \p OldDC can
+/// be redeclared with an unqualfied name in \p NewDC (assuming name lookup
+/// found a declaration in \p OldDC as a previous decl, perhaps through a
+/// using-declaration).
+static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
+ DeclContext *NewDC) {
+ OldDC = OldDC->getRedeclContext();
+ NewDC = NewDC->getRedeclContext();
+
+ if (OldDC->Equals(NewDC))
+ return true;
+
+ // In MSVC mode, we allow a redeclaration if the contexts are related (either
+ // encloses the other).
+ if (S.getLangOpts().MSVCCompat &&
+ (OldDC->Encloses(NewDC) || NewDC->Encloses(OldDC)))
+ return true;
+
+ return false;
+}
+
+/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
///
-/// IsTypeSpecifier is true if this is a type-specifier (or
+/// \param IsTypeSpecifier \c true if this is a type-specifier (or
/// trailing-type-specifier) other than one in an alias-declaration.
+///
+/// \param SkipBody If non-null, will be set to indicate if the caller should
+/// skip the definition of this tag and treat it as if it were a declaration.
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -11163,7 +11498,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag,
TypeResult UnderlyingType,
- bool IsTypeSpecifier) {
+ bool IsTypeSpecifier, SkipBodyInfo *SkipBody) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -11206,7 +11541,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
ModulePrivateLoc,
/*FriendLoc*/SourceLocation(),
TemplateParameterLists.size()-1,
- TemplateParameterLists.data());
+ TemplateParameterLists.data(),
+ SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
@@ -11313,6 +11649,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
goto CreateNewDecl;
}
} else if (Name) {
+ // C++14 [class.mem]p14:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // -- every member of class T that is itself a type
+ if (TUK != TUK_Reference && TUK != TUK_Friend &&
+ DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc)))
+ return nullptr;
+
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
// FIXME: We're looking into outer scopes here, even when we
@@ -11472,10 +11816,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
+ // If we have a known previous declaration to use, then use it.
+ if (Previous.empty() && SkipBody && SkipBody->Previous)
+ Previous.addDecl(SkipBody->Previous);
+
if (!Previous.empty()) {
NamedDecl *PrevDecl = Previous.getFoundDecl();
- NamedDecl *DirectPrevDecl =
- getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl;
+ NamedDecl *DirectPrevDecl = Previous.getRepresentativeDecl();
// It's okay to have a tag decl in the same scope as a typedef
// which hides a tag decl in the same scope. Finding this
@@ -11502,6 +11849,26 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
+ // If this is a redeclaration of a using shadow declaration, it must
+ // declare a tag in the same context. In MSVC mode, we allow a
+ // redefinition if either context is within the other.
+ if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) {
+ auto *OldTag = dyn_cast<TagDecl>(PrevDecl);
+ if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend &&
+ isDeclInScope(Shadow, SearchDC, S, isExplicitSpecialization) &&
+ !(OldTag && isAcceptableTagRedeclContext(
+ *this, OldTag->getDeclContext(), SearchDC))) {
+ Diag(KWLoc, diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl)
+ << 0;
+ // Recover by ignoring the old declaration.
+ Previous.clear();
+ goto CreateNewDecl;
+ }
+ }
+
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
@@ -11513,7 +11880,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
TUK == TUK_Definition, KWLoc,
- *Name)) {
+ Name)) {
bool SafeToContinue
= (PrevTagDecl->getTagKind() != TTK_Enum &&
Kind != TTK_Enum);
@@ -11589,7 +11956,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
- if (TagDecl *Def = PrevTagDecl->getDefinition()) {
+ if (NamedDecl *Def = PrevTagDecl->getDefinition()) {
// If we're defining a specialization and the previous definition
// is from an implicit instantiation, don't emit an error
// here; we'll catch this in the general case below.
@@ -11605,7 +11972,18 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TSK_ExplicitSpecialization;
}
- if (!IsExplicitSpecializationAfterInstantiation) {
+ NamedDecl *Hidden = nullptr;
+ if (SkipBody && getLangOpts().CPlusPlus &&
+ !hasVisibleDefinition(Def, &Hidden)) {
+ // There is a definition of this tag, but it is not visible. We
+ // explicitly make use of C++'s one definition rule here, and
+ // assume that this definition is identical to the hidden one
+ // we already have. Make the existing definition visible and
+ // use it in place of this one.
+ SkipBody->ShouldSkip = true;
+ makeMergedDefinitionVisible(Hidden, KWLoc);
+ return Def;
+ } else if (!IsExplicitSpecializationAfterInstantiation) {
// A redeclaration in function prototype scope in C isn't
// visible elsewhere, so merely issue a warning.
if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope())
@@ -11679,7 +12057,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Invalid = true;
// Otherwise, only diagnose if the declaration is in scope.
- } else if (!isDeclInScope(PrevDecl, SearchDC, S,
+ } else if (!isDeclInScope(DirectPrevDecl, SearchDC, S,
SS.isNotEmpty() || isExplicitSpecialization)) {
// do nothing
@@ -12339,8 +12717,10 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
InvalidDecl = true;
bool ZeroWidth = false;
+ if (InvalidDecl)
+ BitWidth = nullptr;
// If this is declared as a bit-field, check the bit-field.
- if (!InvalidDecl && BitWidth) {
+ if (BitWidth) {
BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth,
&ZeroWidth).get();
if (!BitWidth) {
@@ -12354,7 +12734,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (!InvalidDecl && Mutable) {
unsigned DiagID = 0;
if (T->isReferenceType())
- DiagID = diag::err_mutable_reference;
+ DiagID = getLangOpts().MSVCCompat ? diag::ext_mutable_reference
+ : diag::err_mutable_reference;
else if (T.isConstQualified())
DiagID = diag::err_mutable_const;
@@ -12363,8 +12744,10 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid())
ErrLoc = D->getDeclSpec().getStorageClassSpecLoc();
Diag(ErrLoc, DiagID);
- Mutable = false;
- InvalidDecl = true;
+ if (DiagID != diag::ext_mutable_reference) {
+ Mutable = false;
+ InvalidDecl = true;
+ }
}
}
@@ -13286,6 +13669,29 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
Val, EnumVal);
}
+Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
+ SourceLocation IILoc) {
+ if (!(getLangOpts().Modules || getLangOpts().ModulesLocalVisibility) ||
+ !getLangOpts().CPlusPlus)
+ return SkipBodyInfo();
+
+ // We have an anonymous enum definition. Look up the first enumerator to
+ // determine if we should merge the definition with an existing one and
+ // skip the body.
+ NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName,
+ ForRedeclaration);
+ auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl);
+ NamedDecl *Hidden;
+ if (PrevECD &&
+ !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()),
+ &Hidden)) {
+ SkipBodyInfo Skip;
+ Skip.Previous = Hidden;
+ return Skip;
+ }
+
+ return SkipBodyInfo();
+}
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -13330,12 +13736,9 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// different from T:
// - every enumerator of every member of class T that is an unscoped
// enumerated type
- if (CXXRecordDecl *Record
- = dyn_cast<CXXRecordDecl>(
- TheEnumDecl->getDeclContext()->getRedeclContext()))
- if (!TheEnumDecl->isScoped() &&
- Record->getIdentifier() && Record->getIdentifier() == Id)
- Diag(IdLoc, diag::err_member_name_of_class) << Id;
+ if (!TheEnumDecl->isScoped())
+ DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
+ DeclarationNameInfo(Id, IdLoc));
EnumConstantDecl *New =
CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
@@ -13528,6 +13931,49 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
}
+bool
+Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+ bool AllowMask) const {
+ FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>();
+ assert(FEAttr && "looking for value in non-flag enum");
+
+ llvm::APInt FlagMask = ~FEAttr->getFlagBits();
+ unsigned Width = FlagMask.getBitWidth();
+
+ // We will try a zero-extended value for the regular check first.
+ llvm::APInt ExtVal = Val.zextOrSelf(Width);
+
+ // A value is in a flag enum if either its bits are a subset of the enum's
+ // flag bits (the first condition) or we are allowing masks and the same is
+ // true of its complement (the second condition). When masks are allowed, we
+ // allow the common idiom of ~(enum1 | enum2) to be a valid enum value.
+ //
+ // While it's true that any value could be used as a mask, the assumption is
+ // that a mask will have all of the insignificant bits set. Anything else is
+ // likely a logic error.
+ if (!(FlagMask & ExtVal))
+ return true;
+
+ if (AllowMask) {
+ // Try a one-extended value instead. This can happen if the enum is wider
+ // than the constant used, in C with extensions to allow for wider enums.
+ // The mask will still have the correct behaviour, so we give the user the
+ // benefit of the doubt.
+ //
+ // FIXME: This heuristic can cause weird results if the enum was extended
+ // to a larger type and is signed, because then bit-masks of smaller types
+ // that get extended will fall out of range (e.g. ~0x1u). We currently don't
+ // detect that case and will get a false positive for it. In most cases,
+ // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may
+ // be fine just to accept this as a warning.
+ ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth());
+ if (!(FlagMask & ~ExtVal))
+ return true;
+ }
+
+ return false;
+}
+
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDeclX,
ArrayRef<Decl *> Elements,
@@ -13613,10 +14059,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
BestPromotionType = Context.getPromotedIntegerType(BestType);
else
BestPromotionType = BestType;
- // We don't need to set BestWidth, because BestType is going to be the type
- // of the enumerators, but we do anyway because otherwise some compilers
- // warn that it might be used uninitialized.
- BestWidth = CharWidth;
+
+ BestWidth = Context.getIntWidth(BestType);
}
else if (NumNegativeBits) {
// If there is a negative value, figure out the smallest integer type (of
@@ -13681,10 +14125,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
}
}
+ FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>();
+ if (FEAttr)
+ FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0);
+
// Loop over all of the enumerator constants, changing their types to match
- // the type of the enum if needed.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ // the type of the enum if needed. If we have a flag type, we also prepare the
+ // FlagBits cache.
+ for (auto *D : Elements) {
+ auto *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
// Standard C says the enumerators have int type, but we allow, as an
@@ -13714,7 +14163,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// enum-specifier, each enumerator has the type of its
// enumeration.
ECD->setType(EnumType);
- continue;
+ goto flagbits;
} else {
NewTy = BestType;
NewWidth = BestWidth;
@@ -13741,8 +14190,32 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(EnumType);
else
ECD->setType(NewTy);
+
+flagbits:
+ // Check to see if we have a constant with exactly one bit set. Note that x
+ // & (x - 1) will be nonzero if and only if x has more than one bit set.
+ if (FEAttr) {
+ llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth);
+ if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) {
+ FEAttr->getFlagBits() |= ExtVal;
+ }
+ }
}
+ if (FEAttr) {
+ for (Decl *D : Elements) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D);
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ llvm::APSInt InitVal = ECD->getInitVal();
+ if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true))
+ Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range)
+ << ECD << Enum;
+ }
+ }
+
+
+
Enum->completeDefinition(BestType, BestPromotionType,
NumPositiveBits, NumNegativeBits);
@@ -13804,6 +14277,8 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
if (!Mod)
return true;
+ VisibleModules.setVisible(Mod, ImportLoc);
+
checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
// FIXME: we should support importing a submodule within a different submodule
@@ -13839,9 +14314,46 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
- // FIXME: Should we synthesize an ImportDecl here?
- getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
- /*Complain=*/true);
+ // Determine whether we're in the #include buffer for a module. The #includes
+ // in that buffer do not qualify as module imports; they're just an
+ // implementation detail of us building the module.
+ //
+ // FIXME: Should we even get ActOnModuleInclude calls for those?
+ bool IsInModuleIncludes =
+ TUKind == TU_Module &&
+ getSourceManager().isWrittenInMainFile(DirectiveLoc);
+
+ // If this module import was due to an inclusion directive, create an
+ // implicit import declaration to capture it in the AST.
+ if (!IsInModuleIncludes) {
+ TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
+ ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
+ DirectiveLoc, Mod,
+ DirectiveLoc);
+ TU->addDecl(ImportD);
+ Consumer.HandleImplicitImportDecl(ImportD);
+ }
+
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc);
+ VisibleModules.setVisible(Mod, DirectiveLoc);
+}
+
+void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+
+ if (getLangOpts().ModulesLocalVisibility)
+ VisibleModulesStack.push_back(std::move(VisibleModules));
+ VisibleModules.setVisible(Mod, DirectiveLoc);
+}
+
+void Sema::ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod) {
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+
+ if (getLangOpts().ModulesLocalVisibility) {
+ VisibleModules = std::move(VisibleModulesStack.back());
+ VisibleModulesStack.pop_back();
+ VisibleModules.setVisible(Mod, DirectiveLoc);
+ }
}
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
@@ -13858,8 +14370,8 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
Consumer.HandleImplicitImportDecl(ImportD);
// Make the module visible.
- getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
- /*Complain=*/false);
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc);
+ VisibleModules.setVisible(Mod, Loc);
}
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
@@ -13867,16 +14379,22 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
SourceLocation PragmaLoc,
SourceLocation NameLoc,
SourceLocation AliasNameLoc) {
- Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
- LookupOrdinaryName);
- AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
- AliasName->getName(), 0);
-
- if (PrevDecl)
+ NamedDecl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
+ LookupOrdinaryName);
+ AsmLabelAttr *Attr =
+ AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), AliasNameLoc);
+
+ // If a declaration that:
+ // 1) declares a function or a variable
+ // 2) has external linkage
+ // already exists, add a label attribute to it.
+ if (PrevDecl &&
+ (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)) &&
+ PrevDecl->hasExternalFormalLinkage())
PrevDecl->addAttr(Attr);
- else
- (void)ExtnameUndeclaredIdentifiers.insert(
- std::pair<IdentifierInfo*,AsmLabelAttr*>(Name, Attr));
+ // Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers.
+ else
+ (void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr));
}
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
@@ -13917,7 +14435,10 @@ Decl *Sema::getObjCDeclContext() const {
}
AvailabilityResult Sema::getCurContextAvailability() const {
- const Decl *D = cast<Decl>(getCurObjCLexicalContext());
+ const Decl *D = cast_or_null<Decl>(getCurObjCLexicalContext());
+ if (!D)
+ return AR_Available;
+
// If we are within an Objective-C method, we should consult
// both the availability of the method as well as the
// enclosing class. If the class is (say) deprecated,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index d7ce6f1..191dbd0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -51,6 +52,11 @@ namespace AttributeLangSupport {
static bool isFunctionOrMethod(const Decl *D) {
return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
+/// \brief Return true if the given decl has function type (function or
+/// function-typed variable) or an Objective-C method or a block.
+static bool isFunctionOrMethodOrBlock(const Decl *D) {
+ return isFunctionOrMethod(D) || isa<BlockDecl>(D);
+}
/// Return true if the given decl has a declarator that should have
/// been processed by Sema::GetTypeForDeclarator.
@@ -257,7 +263,7 @@ static bool checkFunctionOrMethodParameterIndex(Sema &S, const Decl *D,
unsigned AttrArgNum,
const Expr *IdxExpr,
uint64_t &Idx) {
- assert(isFunctionOrMethod(D));
+ assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
// Parameters are counted from one.
@@ -351,13 +357,13 @@ static bool isIntOrBool(Expr *Exp) {
// Check to see if the type is a smart pointer of some kind. We assume
// it's a smart pointer if it defines both operator-> and operator*.
static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
- DeclContextLookupConstResult Res1 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
+ DeclContextLookupResult Res1 = RT->getDecl()->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
if (Res1.empty())
return false;
- DeclContextLookupConstResult Res2 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
+ DeclContextLookupResult Res2 = RT->getDecl()->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
if (Res2.empty())
return false;
@@ -1492,6 +1498,20 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
+ // Aliases should be on declarations, not definitions.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isThisDeclarationADefinition()) {
+ S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD;
+ return;
+ }
+ } else {
+ const auto *VD = cast<VarDecl>(D);
+ if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
+ S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD;
+ return;
+ }
+ }
+
// FIXME: check if target symbol exists in current file
D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
@@ -1534,18 +1554,16 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- QualType RetTy = FD->getReturnType();
- if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
- D->addAttr(::new (S.Context)
- MallocAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
- }
+static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ QualType ResultType = getFunctionOrMethodResultType(D);
+ if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
+ D->addAttr(::new (S.Context) RestrictAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ return;
}
- S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+ S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
+ << Attr.getName() << getFunctionOrMethodResultSourceRange(D);
}
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1589,7 +1607,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
// The checking path for 'noreturn' and 'analyzer_noreturn' are different
// because 'analyzer_noreturn' does not impact the type.
- if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
+ if (!isFunctionOrMethodOrBlock(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
@@ -2105,6 +2123,22 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ QualType T = TD->getUnderlyingType();
+ if (!T->isObjCObjectPointerType()) {
+ S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
+ return;
+ }
+ } else {
+ S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ ObjCIndependentClassAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
@@ -2330,6 +2364,15 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
+bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
+ std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
+ if (!Error.empty()) {
+ Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error;
+ return false;
+ }
+ return true;
+}
+
static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Make sure that there is a string literal as the sections's single
// argument.
@@ -2338,6 +2381,9 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
return;
+ if (!S.checkSectionName(LiteralLoc, Str))
+ return;
+
// If the target wants to validate the section specifier, make it happen.
std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
if (!Error.empty()) {
@@ -2352,6 +2398,28 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(NewAttr);
}
+// Check for things we'd like to warn about, no errors or validation for now.
+// TODO: Validation should use a backend target library that specifies
+// the allowable subtarget features and cpus. We could use something like a
+// TargetCodeGenInfo hook here to do validation.
+void Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
+ for (auto Str : {"tune=", "fpmath="})
+ if (AttrStr.find(Str) != StringRef::npos)
+ Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Str;
+}
+
+static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ StringRef Str;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
+ return;
+ S.checkTargetAttr(LiteralLoc, Str);
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ TargetAttr *NewAttr =
+ ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index);
+ D->addAttr(NewAttr);
+}
+
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
VarDecl *VD = cast<VarDecl>(D);
@@ -2482,6 +2550,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) {
.Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
.Case("kprintf", SupportedFormat) // OpenBSD.
.Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
+ .Case("os_trace", SupportedFormat)
.Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
.Default(InvalidFormat);
@@ -2838,6 +2907,16 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
return;
+ if (E->isValueDependent()) {
+ if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
+ if (!TND->getUnderlyingType()->isDependentType()) {
+ S.Diag(Attr.getLoc(), diag::err_alignment_dependent_typedef_name)
+ << E->getSourceRange();
+ return;
+ }
+ }
+ }
+
S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
Attr.isPackExpansion());
}
@@ -2906,11 +2985,27 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
// specifier shall have no effect
// C11 6.7.5p6:
// An alignment specification of zero has no effect.
- if (!(TmpAttr.isAlignas() && !Alignment) &&
- !llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
+ if (!(TmpAttr.isAlignas() && !Alignment)) {
+ if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+ if (Context.getTargetInfo().isTLSSupported()) {
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getTLSKind()) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Alignment.getZExtValue() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ return;
+ }
+ }
+ }
+ }
+ }
}
// Alignment calculations can wrap around if it's greater than 2**28.
@@ -2940,12 +3035,15 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
void Sema::CheckAlignasUnderalignment(Decl *D) {
assert(D->hasAttrs() && "no attributes on decl");
- QualType Ty;
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
- Ty = VD->getType();
- else
- Ty = Context.getTagDeclType(cast<TagDecl>(D));
- if (Ty->isDependentType() || Ty->isIncompleteType())
+ QualType UnderlyingTy, DiagTy;
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ UnderlyingTy = DiagTy = VD->getType();
+ } else {
+ UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
+ if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ UnderlyingTy = ED->getIntegerType();
+ }
+ if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
return;
// C++11 [dcl.align]p5, C11 6.7.5/4:
@@ -2964,10 +3062,10 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
if (AlignasAttr && Align) {
CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
- CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty);
+ CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
if (NaturalAlign > RequestedAlign)
Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
- << Ty << (unsigned)NaturalAlign.getQuantity();
+ << DiagTy << (unsigned)NaturalAlign.getQuantity();
}
}
@@ -3073,16 +3171,22 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
+ // Base type can also be a vector type (see PR17453).
+ // Distinguish between base type and base element type.
+ QualType OldElemTy = OldTy;
+ if (const VectorType *VT = OldTy->getAs<VectorType>())
+ OldElemTy = VT->getElementType();
+
+ if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType())
S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
else if (IntegerMode) {
- if (!OldTy->isIntegralOrEnumerationType())
+ if (!OldElemTy->isIntegralOrEnumerationType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
} else if (ComplexMode) {
- if (!OldTy->isComplexType())
+ if (!OldElemTy->isComplexType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
} else {
- if (!OldTy->isFloatingType())
+ if (!OldElemTy->isFloatingType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
}
@@ -3095,21 +3199,40 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- QualType NewTy;
+ QualType NewElemTy;
if (IntegerMode)
- NewTy = S.Context.getIntTypeForBitwidth(DestWidth,
- OldTy->isSignedIntegerType());
+ NewElemTy = S.Context.getIntTypeForBitwidth(
+ DestWidth, OldElemTy->isSignedIntegerType());
else
- NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
+ NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth);
- if (NewTy.isNull()) {
+ if (NewElemTy.isNull()) {
S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
return;
}
if (ComplexMode) {
- NewTy = S.Context.getComplexType(NewTy);
+ NewElemTy = S.Context.getComplexType(NewElemTy);
+ }
+
+ QualType NewTy = NewElemTy;
+ if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
+ // Complex machine mode does not support base vector types.
+ if (ComplexMode) {
+ S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type);
+ return;
+ }
+ unsigned NumElements = S.Context.getTypeSize(OldElemTy) *
+ OldVT->getNumElements() /
+ S.Context.getTypeSize(NewElemTy);
+ NewTy =
+ S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
+ }
+
+ if (NewTy.isNull()) {
+ S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ return;
}
// Install the new type.
@@ -3243,11 +3366,10 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (hasDeclarator(D)) return;
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
// Diagnostic is emitted elsewhere: here we store the (valid) Attr
// in the Decl node for syntactic reasoning, e.g., pretty-printing.
CallingConv CC;
- if (S.CheckCallingConvAttr(Attr, CC, FD))
+ if (S.CheckCallingConvAttr(Attr, CC, /*FD*/nullptr))
return;
if (!isa<ObjCMethodDecl>(D)) {
@@ -3315,11 +3437,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
return;
}
- case AttributeList::AT_PnaclCall:
- D->addAttr(::new (S.Context)
- PnaclCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
case AttributeList::AT_IntelOclBicc:
D->addAttr(::new (S.Context)
IntelOclBiccAttr(Attr.getRange(), S.Context,
@@ -3376,16 +3493,18 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
Diag(attr.getLoc(), diag::err_invalid_pcs);
return true;
}
- case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break;
case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
default: llvm_unreachable("unexpected attribute kind");
}
const TargetInfo &TI = Context.getTargetInfo();
TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
- if (A == TargetInfo::CCCR_Warning) {
- Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
+ if (A != TargetInfo::CCCR_OK) {
+ if (A == TargetInfo::CCCR_Warning)
+ Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
+ // This convention is not valid for the target. Use the default function or
+ // method calling convention.
TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown;
if (FD)
MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :
@@ -3432,20 +3551,63 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
return false;
}
+// Checks whether an argument of launch_bounds attribute is acceptable
+// May output an error.
+static bool checkLaunchBoundsArgument(Sema &S, Expr *E,
+ const CUDALaunchBoundsAttr &Attr,
+ const unsigned Idx) {
+
+ if (S.DiagnoseUnexpandedParameterPack(E))
+ return false;
+
+ // Accept template arguments for now as they depend on something else.
+ // We'll get to check them when they eventually get instantiated.
+ if (E->isValueDependent())
+ return true;
+
+ llvm::APSInt I(64);
+ if (!E->isIntegerConstantExpr(I, S.Context)) {
+ S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
+ << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
+ return false;
+ }
+ // Make sure we can fit it in 32 bits.
+ if (!I.isIntN(32)) {
+ S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false)
+ << 32 << /* Unsigned */ 1;
+ return false;
+ }
+ if (I < 0)
+ S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
+ << &Attr << Idx << E->getSourceRange();
+
+ return true;
+}
+
+void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
+ Expr *MinBlocks, unsigned SpellingListIndex) {
+ CUDALaunchBoundsAttr TmpAttr(AttrRange, Context, MaxThreads, MinBlocks,
+ SpellingListIndex);
+
+ if (!checkLaunchBoundsArgument(*this, MaxThreads, TmpAttr, 0))
+ return;
+
+ if (MinBlocks && !checkLaunchBoundsArgument(*this, MinBlocks, TmpAttr, 1))
+ return;
+
+ D->addAttr(::new (Context) CUDALaunchBoundsAttr(
+ AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex));
+}
+
static void handleLaunchBoundsAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- uint32_t MaxThreads, MinBlocks = 0;
- if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1))
- return;
- if (Attr.getNumArgs() > 1 && !checkUInt32Argument(S, Attr,
- Attr.getArgAsExpr(1),
- MinBlocks, 2))
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
+ !checkAttributeAtMostNumArgs(S, Attr, 2))
return;
- D->addAttr(::new (S.Context)
- CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
- MaxThreads, MinBlocks,
- Attr.getAttributeSpellingListIndex()));
+ S.AddLaunchBoundsAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
+ Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr,
+ Attr.getAttributeSpellingListIndex());
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
@@ -3585,10 +3747,31 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
returnType = PD->getType();
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
returnType = FD->getReturnType();
- else {
+ else if (auto *Param = dyn_cast<ParmVarDecl>(D)) {
+ returnType = Param->getType()->getPointeeType();
+ if (returnType.isNull()) {
+ S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
+ << Attr.getName() << /*pointer-to-CF*/2
+ << Attr.getRange();
+ return;
+ }
+ } else {
+ AttributeDeclKind ExpectedDeclKind;
+ switch (Attr.getKind()) {
+ default: llvm_unreachable("invalid ownership attribute");
+ case AttributeList::AT_NSReturnsRetained:
+ case AttributeList::AT_NSReturnsAutoreleased:
+ case AttributeList::AT_NSReturnsNotRetained:
+ ExpectedDeclKind = ExpectedFunctionOrMethod;
+ break;
+
+ case AttributeList::AT_CFReturnsRetained:
+ case AttributeList::AT_CFReturnsNotRetained:
+ ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
+ break;
+ }
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName()
- << ExpectedFunctionOrMethod;
+ << Attr.getRange() << Attr.getName() << ExpectedDeclKind;
return;
}
@@ -3615,8 +3798,25 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
}
if (!typeOK) {
- S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf;
+ if (isa<ParmVarDecl>(D)) {
+ S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
+ << Attr.getName() << /*pointer-to-CF*/2
+ << Attr.getRange();
+ } else {
+ // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
+ enum : unsigned {
+ Function,
+ Method,
+ Property
+ } SubjectKind = Function;
+ if (isa<ObjCMethodDecl>(D))
+ SubjectKind = Method;
+ else if (isa<ObjCPropertyDecl>(D))
+ SubjectKind = Property;
+ S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+ << Attr.getName() << SubjectKind << cf
+ << Attr.getRange();
+ }
return;
}
@@ -3724,6 +3924,22 @@ static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
}
+
+ // Typedefs only allow objc_bridge(id) and have some additional checking.
+ if (auto TD = dyn_cast<TypedefNameDecl>(D)) {
+ if (!Parm->Ident->isStr("id")) {
+ S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_id)
+ << Attr.getName();
+ return;
+ }
+
+ // Only allow 'cv void *'.
+ QualType T = TD->getUnderlyingType();
+ if (!T->isVoidPointerType()) {
+ S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
+ return;
+ }
+ }
D->addAttr(::new (S.Context)
ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
@@ -3770,6 +3986,10 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
IFace = CatDecl->getClassInterface();
else
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
+
+ if (!IFace)
+ return;
+
IFace->setHasDesignatedInitializers();
D->addAttr(::new (S.Context)
ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
@@ -3787,6 +4007,34 @@ static void handleObjCRuntimeName(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+// when a user wants to use objc_boxable with a union or struct
+// but she doesn't have access to the declaration (legacy/third-party code)
+// then she can 'enable' this feature via trick with a typedef
+// e.g.:
+// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
+static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
+ bool notify = false;
+
+ RecordDecl *RD = dyn_cast<RecordDecl>(D);
+ if (RD && RD->getDefinition()) {
+ RD = RD->getDefinition();
+ notify = true;
+ }
+
+ if (RD) {
+ ObjCBoxableAttr *BoxableAttr = ::new (S.Context)
+ ObjCBoxableAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex());
+ RD->addAttr(BoxableAttr);
+ if (notify) {
+ // we need to notify ASTReader/ASTWriter about
+ // modification of existing declaration
+ if (ASTMutationListener *L = S.getASTMutationListener())
+ L->AddedAttributeToRecord(BoxableAttr, RD);
+ }
+ }
+}
+
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (hasDeclarator(D)) return;
@@ -4226,9 +4474,52 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
}
+
+ if (!S.getLangOpts().CPlusPlus14)
+ if (Attr.isCXX11Attribute() &&
+ !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu")))
+ S.Diag(Attr.getLoc(), diag::ext_deprecated_attr_is_a_cxx14_extension);
+
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
}
+static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ std::vector<std::string> Sanitizers;
+
+ for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ StringRef SanitizerName;
+ SourceLocation LiteralLoc;
+
+ if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc))
+ return;
+
+ if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0)
+ S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
+
+ Sanitizers.push_back(SanitizerName);
+ }
+
+ D->addAttr(::new (S.Context) NoSanitizeAttr(
+ Attr.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ std::string SanitizerName =
+ llvm::StringSwitch<std::string>(Attr.getName()->getName())
+ .Case("no_address_safety_analysis", "address")
+ .Case("no_sanitize_address", "address")
+ .Case("no_sanitize_thread", "thread")
+ .Case("no_sanitize_memory", "memory");
+ D->addAttr(::new (S.Context)
+ NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1,
+ Attr.getAttributeSpellingListIndex()));
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -4396,6 +4687,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_OptimizeNone:
handleOptimizeNoneAttr(S, D, Attr);
break;
+ case AttributeList::AT_FlagEnum:
+ handleSimpleAttribute<FlagEnumAttr>(S, D, Attr);
+ break;
case AttributeList::AT_Flatten:
handleSimpleAttribute<FlattenAttr>(S, D, Attr);
break;
@@ -4420,8 +4714,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_CUDALaunchBounds:
handleLaunchBoundsAttr(S, D, Attr);
break;
- case AttributeList::AT_Malloc:
- handleMallocAttr(S, D, Attr);
+ case AttributeList::AT_Restrict:
+ handleRestrictAttr(S, D, Attr);
break;
case AttributeList::AT_MayAlias:
handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
@@ -4509,6 +4803,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCRuntimeName:
handleObjCRuntimeName(S, D, Attr);
break;
+
+ case AttributeList::AT_ObjCBoxable:
+ handleObjCBoxable(S, D, Attr);
+ break;
case AttributeList::AT_CFAuditedTransfer:
handleCFAuditedTransferAttr(S, D, Attr);
@@ -4552,6 +4850,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Section:
handleSectionAttr(S, D, Attr);
break;
+ case AttributeList::AT_Target:
+ handleTargetAttr(S, D, Attr);
+ break;
case AttributeList::AT_Unavailable:
handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
break;
@@ -4609,6 +4910,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCNSObject:
handleObjCNSObject(S, D, Attr);
break;
+ case AttributeList::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, Attr);
+ break;
case AttributeList::AT_Blocks:
handleBlocksAttr(S, D, Attr);
break;
@@ -4645,7 +4949,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_MSABI:
case AttributeList::AT_SysVABI:
case AttributeList::AT_Pcs:
- case AttributeList::AT_PnaclCall:
case AttributeList::AT_IntelOclBicc:
handleCallConvAttr(S, D, Attr);
break;
@@ -4657,8 +4960,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
break;
// Microsoft attributes:
- case AttributeList::AT_MsStruct:
- handleSimpleAttribute<MsStructAttr>(S, D, Attr);
+ case AttributeList::AT_MSNoVTable:
+ handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_MSStruct:
+ handleSimpleAttribute<MSStructAttr>(S, D, Attr);
break;
case AttributeList::AT_Uuid:
handleUuidAttr(S, D, Attr);
@@ -4689,18 +4995,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ScopedLockable:
handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
break;
- case AttributeList::AT_NoSanitizeAddress:
- handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
+ case AttributeList::AT_NoSanitize:
+ handleNoSanitizeAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoSanitizeSpecific:
+ handleNoSanitizeSpecificAttr(S, D, Attr);
break;
case AttributeList::AT_NoThreadSafetyAnalysis:
handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
break;
- case AttributeList::AT_NoSanitizeThread:
- handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr);
- break;
- case AttributeList::AT_NoSanitizeMemory:
- handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr);
- break;
case AttributeList::AT_GuardedBy:
handleGuardedByAttr(S, D, Attr);
break;
@@ -4963,8 +5266,7 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
ND = FD;
if (ND) {
if (IdentifierInfo *Id = ND->getIdentifier()) {
- llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
- = WeakUndeclaredIdentifiers.find(Id);
+ auto I = WeakUndeclaredIdentifiers.find(Id);
if (I != WeakUndeclaredIdentifiers.end()) {
WeakInfo W = I->second;
DeclApplyPragmaWeak(S, ND, W);
@@ -5043,7 +5345,8 @@ static bool isDeclDeprecated(Decl *D) {
return true;
// A category implicitly has the availability of the interface.
if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
- return CatD->getClassInterface()->isDeprecated();
+ if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
+ return Interface->isDeprecated();
} while ((D = cast_or_null<Decl>(D->getDeclContext())));
return false;
}
@@ -5054,12 +5357,13 @@ static bool isDeclUnavailable(Decl *D) {
return true;
// A category implicitly has the availability of the interface.
if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
- return CatD->getClassInterface()->isUnavailable();
+ if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
+ return Interface->isUnavailable();
} while ((D = cast_or_null<Decl>(D->getDeclContext())));
return false;
}
-static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
+static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
Decl *Ctx, const NamedDecl *D,
StringRef Message, SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -5076,8 +5380,8 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
// Don't warn if our current context is deprecated or unavailable.
switch (K) {
- case DelayedDiagnostic::Deprecation:
- if (isDeclDeprecated(Ctx))
+ case Sema::AD_Deprecation:
+ if (isDeclDeprecated(Ctx) || isDeclUnavailable(Ctx))
return;
diag = !ObjCPropertyAccess ? diag::warn_deprecated
: diag::warn_property_method_deprecated;
@@ -5087,7 +5391,7 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
available_here_select_kind = /* deprecated */ 2;
break;
- case DelayedDiagnostic::Unavailable:
+ case Sema::AD_Unavailable:
if (isDeclUnavailable(Ctx))
return;
diag = !ObjCPropertyAccess ? diag::err_unavailable
@@ -5098,8 +5402,13 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
available_here_select_kind = /* unavailable */ 0;
break;
- default:
- llvm_unreachable("Neither a deprecation or unavailable kind");
+ case Sema::AD_Partial:
+ diag = diag::warn_partial_availability;
+ diag_message = diag::warn_partial_message;
+ diag_fwdclass_message = diag::warn_partial_fwdclass_message;
+ property_note_select = /* partial */ 2;
+ available_here_select_kind = /* partial */ 3;
+ break;
}
if (!Message.empty()) {
@@ -5119,15 +5428,21 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
S.Diag(D->getLocation(), diag::note_availability_specified_here)
<< D << available_here_select_kind;
+ if (K == Sema::AD_Partial)
+ S.Diag(Loc, diag::note_partial_availability_silence) << D;
}
static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
Decl *Ctx) {
+ assert(DD.Kind == DelayedDiagnostic::Deprecation ||
+ DD.Kind == DelayedDiagnostic::Unavailable);
+ Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation
+ ? Sema::AD_Deprecation
+ : Sema::AD_Unavailable;
DD.Triggered = true;
- DoEmitAvailabilityWarning(S, (DelayedDiagnostic::DDKind)DD.Kind, Ctx,
- DD.getDeprecationDecl(), DD.getDeprecationMessage(),
- DD.Loc, DD.getUnknownObjCClass(),
- DD.getObjCProperty(), false);
+ DoEmitAvailabilityWarning(
+ S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc,
+ DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -5193,7 +5508,7 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
// Delay if we're currently parsing a declaration.
- if (DelayedDiagnostics.shouldDelayDiagnostics()) {
+ if (DelayedDiagnostics.shouldDelayDiagnostics() && AD != AD_Partial) {
DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
AD, Loc, D, UnknownObjCClass, ObjCProperty, Message,
ObjCPropertyAccess));
@@ -5201,16 +5516,6 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
}
Decl *Ctx = cast<Decl>(getCurLexicalContext());
- DelayedDiagnostic::DDKind K;
- switch (AD) {
- case AD_Deprecation:
- K = DelayedDiagnostic::Deprecation;
- break;
- case AD_Unavailable:
- K = DelayedDiagnostic::Unavailable;
- break;
- }
-
- DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
- UnknownObjCClass, ObjCProperty, ObjCPropertyAccess);
+ DoEmitAvailabilityWarning(*this, AD, Ctx, D, Message, Loc, UnknownObjCClass,
+ ObjCProperty, ObjCPropertyAccess);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 510738e..0d7cbf4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -73,8 +73,8 @@ namespace {
/// VisitExpr - Visit all of the children of this expression.
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
bool IsInvalid = false;
- for (Stmt::child_range I = Node->children(); I; ++I)
- IsInvalid |= Visit(*I);
+ for (Stmt *SubStmt : Node->children())
+ IsInvalid |= Visit(SubStmt);
return IsInvalid;
}
@@ -316,8 +316,17 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
Param->setInvalidDecl();
return;
- }
-
+ }
+
+ // C++11 [dcl.fct.default]p3
+ // A default argument expression [...] shall not be specified for a
+ // parameter pack.
+ if (Param->isParameterPack()) {
+ Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack)
+ << DefaultArg->getSourceRange();
+ return;
+ }
+
// Check that the default argument is well-formed
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
if (DefaultArgChecker.Visit(DefaultArg)) {
@@ -429,6 +438,45 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Scope *S) {
bool Invalid = false;
+ // The declaration context corresponding to the scope is the semantic
+ // parent, unless this is a local function declaration, in which case
+ // it is that surrounding function.
+ DeclContext *ScopeDC = New->isLocalExternDecl()
+ ? New->getLexicalDeclContext()
+ : New->getDeclContext();
+
+ // Find the previous declaration for the purpose of default arguments.
+ FunctionDecl *PrevForDefaultArgs = Old;
+ for (/**/; PrevForDefaultArgs;
+ // Don't bother looking back past the latest decl if this is a local
+ // extern declaration; nothing else could work.
+ PrevForDefaultArgs = New->isLocalExternDecl()
+ ? nullptr
+ : PrevForDefaultArgs->getPreviousDecl()) {
+ // Ignore hidden declarations.
+ if (!LookupResult::isVisible(*this, PrevForDefaultArgs))
+ continue;
+
+ if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) &&
+ !New->isCXXClassMember()) {
+ // Ignore default arguments of old decl if they are not in
+ // the same scope and this is not an out-of-line definition of
+ // a member function.
+ continue;
+ }
+
+ if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) {
+ // If only one of these is a local function declaration, then they are
+ // declared in different scopes, even though isDeclInScope may think
+ // they're in the same scope. (If both are local, the scope check is
+ // sufficent, and if neither is local, then they are in the same scope.)
+ continue;
+ }
+
+ // We found our guy.
+ break;
+ }
+
// C++ [dcl.fct.default]p4:
// For non-template functions, default arguments can be added in
// later declarations of a function in the same
@@ -447,34 +495,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// in a member function definition that appears outside of the class
// definition are added to the set of default arguments provided by the
// member function declaration in the class definition.
- for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
- ParmVarDecl *OldParam = Old->getParamDecl(p);
+ for (unsigned p = 0, NumParams = PrevForDefaultArgs
+ ? PrevForDefaultArgs->getNumParams()
+ : 0;
+ p < NumParams; ++p) {
+ ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p);
ParmVarDecl *NewParam = New->getParamDecl(p);
- bool OldParamHasDfl = OldParam->hasDefaultArg();
+ bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false;
bool NewParamHasDfl = NewParam->hasDefaultArg();
- // The declaration context corresponding to the scope is the semantic
- // parent, unless this is a local function declaration, in which case
- // it is that surrounding function.
- DeclContext *ScopeDC = New->isLocalExternDecl()
- ? New->getLexicalDeclContext()
- : New->getDeclContext();
- if (S && !isDeclInScope(Old, ScopeDC, S) &&
- !New->getDeclContext()->isRecord())
- // Ignore default parameters of old decl if they are not in
- // the same scope and this is not an out-of-line definition of
- // a member function.
- OldParamHasDfl = false;
- if (New->isLocalExternDecl() != Old->isLocalExternDecl())
- // If only one of these is a local function declaration, then they are
- // declared in different scopes, even though isDeclInScope may think
- // they're in the same scope. (If both are local, the scope check is
- // sufficent, and if neither is local, then they are in the same scope.)
- OldParamHasDfl = false;
-
if (OldParamHasDfl && NewParamHasDfl) {
-
unsigned DiagDefaultParamID =
diag::err_param_default_argument_redefinition;
@@ -482,7 +513,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// of template class. The new default parameter's value is ignored.
Invalid = true;
if (getLangOpts().MicrosoftExt) {
- CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New);
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New);
if (MD && MD->getParent()->getDescribedClassTemplate()) {
// Merge the old default argument into the new parameter.
NewParam->setHasInheritedDefaultArg();
@@ -509,14 +540,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// Look for the function declaration where the default argument was
// actually written, which may be a declaration prior to Old.
- for (FunctionDecl *Older = Old->getPreviousDecl();
- Older; Older = Older->getPreviousDecl()) {
- if (!Older->getParamDecl(p)->hasDefaultArg())
- break;
-
+ for (auto Older = PrevForDefaultArgs;
+ OldParam->hasInheritedDefaultArg(); /**/) {
+ Older = Older->getPreviousDecl();
OldParam = Older->getParamDecl(p);
- }
-
+ }
+
Diag(OldParam->getLocation(), diag::note_previous_definition)
<< OldParam->getDefaultArgRange();
} else if (OldParamHasDfl) {
@@ -524,7 +553,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// It's important to use getInit() here; getDefaultArg()
// strips off any top-level ExprWithCleanups.
NewParam->setHasInheritedDefaultArg();
- if (OldParam->hasUninstantiatedDefaultArg())
+ if (OldParam->hasUnparsedDefaultArg())
+ NewParam->setUnparsedDefaultArg();
+ else if (OldParam->hasUninstantiatedDefaultArg())
NewParam->setUninstantiatedDefaultArg(
OldParam->getUninstantiatedDefaultArg());
else
@@ -535,8 +566,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Diag(NewParam->getLocation(),
diag::err_param_default_argument_template_redecl)
<< NewParam->getDefaultArgRange();
- Diag(Old->getLocation(), diag::note_template_prev_declaration)
- << false;
+ Diag(PrevForDefaultArgs->getLocation(),
+ diag::note_template_prev_declaration)
+ << false;
} else if (New->getTemplateSpecializationKind()
!= TSK_ImplicitInstantiation &&
New->getTemplateSpecializationKind() != TSK_Undeclared) {
@@ -607,7 +639,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
- } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+ } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
+ Old->isDefined(Def)) {
// C++11 [dcl.fcn.spec]p4:
// If the definition of a function appears in a translation unit before its
// first declaration as inline, the program is ill-formed.
@@ -689,16 +722,16 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
break;
}
- // C++ [dcl.fct.default]p4:
- // In a given function declaration, all parameters
- // subsequent to a parameter with a default argument shall
- // have default arguments supplied in this or previous
- // declarations. A default argument shall not be redefined
- // by a later declaration (not even to the same value).
+ // C++11 [dcl.fct.default]p4:
+ // In a given function declaration, each parameter subsequent to a parameter
+ // with a default argument shall have a default argument supplied in this or
+ // a previous declaration or shall be a function parameter pack. A default
+ // argument shall not be redefined by a later declaration (not even to the
+ // same value).
unsigned LastMissingDefaultArg = 0;
for (; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
- if (!Param->hasDefaultArg()) {
+ if (!Param->hasDefaultArg() && !Param->isParameterPack()) {
if (Param->isInvalidDecl())
/* We already complained about this parameter. */;
else if (Param->getIdentifier())
@@ -795,7 +828,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
// - it shall not be virtual;
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
if (Method && Method->isVirtual()) {
- Diag(NewFD->getLocation(), diag::err_constexpr_virtual);
+ Method = Method->getCanonicalDecl();
+ Diag(Method->getLocation(), diag::err_constexpr_virtual);
// If it's not obvious why this function is virtual, find an overridden
// function which uses the 'virtual' keyword.
@@ -1057,9 +1091,9 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
break;
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getLocStart();
- for (Stmt::child_range Children = S->children(); Children; ++Children)
- if (*Children &&
- !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, ReturnStmts,
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc))
return false;
return true;
@@ -1072,9 +1106,9 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
// mutation, we can reasonably allow them in C++11 as an extension.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getLocStart();
- for (Stmt::child_range Children = S->children(); Children; ++Children)
- if (*Children &&
- !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, ReturnStmts,
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc))
return false;
return true;
@@ -1311,57 +1345,6 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
return false;
}
-/// \brief Perform propagation of DLL attributes from a derived class to a
-/// templated base class for MS compatibility.
-static void propagateDLLAttrToBaseClassTemplate(
- Sema &S, CXXRecordDecl *Class, Attr *ClassAttr,
- ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) {
- if (getDLLAttr(
- BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) {
- // If the base class template has a DLL attribute, don't try to change it.
- return;
- }
-
- if (BaseTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
- // If the base class is not already specialized, we can do the propagation.
- auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
- NewAttr->setInherited(true);
- BaseTemplateSpec->addAttr(NewAttr);
- return;
- }
-
- bool DifferentAttribute = false;
- if (Attr *SpecializationAttr = getDLLAttr(BaseTemplateSpec)) {
- if (!SpecializationAttr->isInherited()) {
- // The template has previously been specialized or instantiated with an
- // explicit attribute. We should not try to change it.
- return;
- }
- if (SpecializationAttr->getKind() == ClassAttr->getKind()) {
- // The specialization already has the right attribute.
- return;
- }
- DifferentAttribute = true;
- }
-
- // The template was previously instantiated or explicitly specialized without
- // a dll attribute, or the template was previously instantiated with a
- // different inherited attribute. It's too late for us to change the
- // attribute, so warn that this is unsupported.
- S.Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
- << BaseTemplateSpec->isExplicitSpecialization() << DifferentAttribute;
- S.Diag(ClassAttr->getLocation(), diag::note_attribute);
- if (BaseTemplateSpec->isExplicitSpecialization()) {
- S.Diag(BaseTemplateSpec->getLocation(),
- diag::note_template_class_explicit_specialization_was_here)
- << BaseTemplateSpec;
- } else {
- S.Diag(BaseTemplateSpec->getPointOfInstantiation(),
- diag::note_template_class_instantiation_was_here)
- << BaseTemplateSpec;
- }
-}
-
/// \brief Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
@@ -1433,8 +1416,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (Attr *ClassAttr = getDLLAttr(Class)) {
if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
BaseType->getAsCXXRecordDecl())) {
- propagateDLLAttrToBaseClassTemplate(*this, Class, ClassAttr,
- BaseTemplate, BaseLoc);
+ propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate,
+ BaseLoc);
}
}
}
@@ -1545,6 +1528,31 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
return true;
}
+/// Use small set to collect indirect bases. As this is only used
+/// locally, there's no need to abstract the small size parameter.
+typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
+
+/// \brief Recursively add the bases of Type. Don't add Type itself.
+static void
+NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
+ const QualType &Type)
+{
+ // Even though the incoming type is a base, it might not be
+ // a class -- it could be a template parm, for instance.
+ if (auto Rec = Type->getAs<RecordType>()) {
+ auto Decl = Rec->getAsCXXRecordDecl();
+
+ // Iterate over its bases.
+ for (const auto &BaseSpec : Decl->bases()) {
+ QualType Base = Context.getCanonicalType(BaseSpec.getType())
+ .getUnqualifiedType();
+ if (Set.insert(Base).second)
+ // If we've not already seen it, recurse.
+ NoteIndirectBases(Context, Set, Base);
+ }
+ }
+}
+
/// \brief Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
@@ -1558,6 +1566,10 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
// class.
std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
+ // Used to track indirect bases so we can see if a direct base is
+ // ambiguous.
+ IndirectBaseSet IndirectBaseTypes;
+
// Copy non-redundant base specifiers into permanent storage.
unsigned NumGoodBases = 0;
bool Invalid = false;
@@ -1585,6 +1597,11 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
// Okay, add this new base class.
KnownBase = Bases[idx];
Bases[NumGoodBases++] = Bases[idx];
+
+ // Note this base's direct & indirect bases, if there could be ambiguity.
+ if (NumBases > 1)
+ NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
+
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
if (Class->isInterface() &&
@@ -1605,11 +1622,33 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases, NumGoodBases);
+
+ for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
+ // Check whether this direct base is inaccessible due to ambiguity.
+ QualType BaseType = Bases[idx]->getType();
+ CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
+ .getUnqualifiedType();
+
+ if (IndirectBaseTypes.count(CanonicalBase)) {
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/true);
+ bool found
+ = Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths);
+ assert(found);
+ (void)found;
+
+ if (Paths.isAmbiguous(CanonicalBase))
+ Diag(Bases[idx]->getLocStart (), diag::warn_inaccessible_base_class)
+ << BaseType << getAmbiguousPathsDisplayString(Paths)
+ << Bases[idx]->getSourceRange();
+ else
+ assert(Bases[idx]->isVirtual());
+ }
- // Delete the remaining (good) base class specifiers, since their
- // data has been copied into the CXXRecordDecl.
- for (unsigned idx = 0; idx < NumGoodBases; ++idx)
+ // Delete the base class specifier, since its data has been copied
+ // into the CXXRecordDecl.
Context.Deallocate(Bases[idx]);
+ }
return Invalid;
}
@@ -1689,18 +1728,6 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}
-/// \brief Determine whether the given base path includes a virtual
-/// base class.
-bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) {
- for (CXXCastPath::const_iterator B = BasePath.begin(),
- BEnd = BasePath.end();
- B != BEnd; ++B)
- if ((*B)->isVirtual())
- return true;
-
- return false;
-}
-
/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
/// conversion (where Derived and Base are class types) is
/// well-formed, meaning that the conversion is unambiguous (and
@@ -2159,8 +2186,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(Member && "HandleField never returns null");
}
} else {
- assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
-
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member)
return nullptr;
@@ -3537,8 +3562,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
Expr *CtorArgE = CtorArg.getAs<Expr>();
- InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, CtorArgE);
-
+ InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
+ CtorArgE);
+
ExprResult MemberInit
= InitSeq.Perform(SemaRef, Entities.back(), InitKind,
MultiExprArg(&CtorArgE, 1));
@@ -4659,15 +4685,15 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
/// \brief Check class-level dllimport/dllexport attribute.
-static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
+void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
- auto *A = cast<InheritableAttr>(TemplateAttr->clone(S.getASTContext()));
+ auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext()));
A->setInherited(true);
ClassAttr = A;
}
@@ -4678,12 +4704,12 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
return;
if (!Class->isExternallyVisible()) {
- S.Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
+ Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
<< Class << ClassAttr;
return;
}
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
@@ -4693,10 +4719,10 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
continue;
- S.Diag(MemberAttr->getLocation(),
+ Diag(MemberAttr->getLocation(),
diag::err_attribute_dll_member_of_dll_class)
<< MemberAttr << ClassAttr;
- S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
+ Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
Member->setInvalidDecl();
}
}
@@ -4709,15 +4735,21 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
const bool ClassImported = !ClassExported;
+ TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
+
+ // Ignore explicit dllexport on explicit class template instantiation declarations.
+ if (ClassExported && !ClassAttr->isInherited() &&
+ TSK == TSK_ExplicitInstantiationDeclaration) {
+ Class->dropAttr<DLLExportAttr>();
+ return;
+ }
+
// Force declaration of implicit members so they can inherit the attribute.
- S.ForceDeclarationOfImplicitMembers(Class);
+ ForceDeclarationOfImplicitMembers(Class);
// FIXME: MSVC's docs say all bases must be exportable, but this doesn't
// seem to be true in practice?
- TemplateSpecializationKind TSK =
- Class->getTemplateSpecializationKind();
-
for (Decl *Member : Class->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(Member);
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
@@ -4731,37 +4763,43 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (MD->isDeleted())
continue;
- if (MD->isMoveAssignmentOperator() && ClassImported && MD->isInlined()) {
- // Current MSVC versions don't export the move assignment operators, so
- // don't attempt to import them if we have a definition.
- continue;
- }
+ if (MD->isInlined()) {
+ // MinGW does not import or export inline methods.
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
+ continue;
- if (MD->isInlined() && ClassImported &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // MinGW does not import inline functions.
- continue;
+ // MSVC versions before 2015 don't export the move assignment operators,
+ // so don't attempt to import them if we have a definition.
+ if (ClassImported && MD->isMoveAssignmentOperator() &&
+ !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
+ continue;
}
}
+ if (!cast<NamedDecl>(Member)->isExternallyVisible())
+ continue;
+
if (!getDLLAttr(Member)) {
auto *NewAttr =
- cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
+ cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
}
if (MD && ClassExported) {
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ // Don't go any further if this is just an explicit instantiation
+ // declaration.
+ continue;
+
if (MD->isUserProvided()) {
// Instantiate non-default class member functions ...
// .. except for certain kinds of template specializations.
- if (TSK == TSK_ExplicitInstantiationDeclaration)
- continue;
if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
continue;
- S.MarkFunctionReferenced(Class->getLocation(), MD);
+ MarkFunctionReferenced(Class->getLocation(), MD);
// The function will be passed to the consumer when its definition is
// encountered.
@@ -4772,16 +4810,77 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
// defaulted methods, and the copy and move assignment operators. The
// latter are exported even if they are trivial, because the address of
// an operator can be taken and should compare equal accross libraries.
- S.MarkFunctionReferenced(Class->getLocation(), MD);
+ DiagnosticErrorTrap Trap(Diags);
+ MarkFunctionReferenced(Class->getLocation(), MD);
+ if (Trap.hasErrorOccurred()) {
+ Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
+ << Class->getName() << !getLangOpts().CPlusPlus11;
+ break;
+ }
// There is no later point when we will see the definition of this
// function, so pass it to the consumer now.
- S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
}
}
}
}
+/// \brief Perform propagation of DLL attributes from a derived class to a
+/// templated base class for MS compatibility.
+void Sema::propagateDLLAttrToBaseClassTemplate(
+ CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) {
+ if (getDLLAttr(
+ BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) {
+ // If the base class template has a DLL attribute, don't try to change it.
+ return;
+ }
+
+ auto TSK = BaseTemplateSpec->getSpecializationKind();
+ if (!getDLLAttr(BaseTemplateSpec) &&
+ (TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration ||
+ TSK == TSK_ImplicitInstantiation)) {
+ // The template hasn't been instantiated yet (or it has, but only as an
+ // explicit instantiation declaration or implicit instantiation, which means
+ // we haven't codegenned any members yet), so propagate the attribute.
+ auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ BaseTemplateSpec->addAttr(NewAttr);
+
+ // If the template is already instantiated, checkDLLAttributeRedeclaration()
+ // needs to be run again to work see the new attribute. Otherwise this will
+ // get run whenever the template is instantiated.
+ if (TSK != TSK_Undeclared)
+ checkClassLevelDLLAttribute(BaseTemplateSpec);
+
+ return;
+ }
+
+ if (getDLLAttr(BaseTemplateSpec)) {
+ // The template has already been specialized or instantiated with an
+ // attribute, explicitly or through propagation. We should not try to change
+ // it.
+ return;
+ }
+
+ // The template was previously instantiated or explicitly specialized without
+ // a dll attribute, It's too late for us to add an attribute, so warn that
+ // this is unsupported.
+ Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
+ << BaseTemplateSpec->isExplicitSpecialization();
+ Diag(ClassAttr->getLocation(), diag::note_attribute);
+ if (BaseTemplateSpec->isExplicitSpecialization()) {
+ Diag(BaseTemplateSpec->getLocation(),
+ diag::note_template_class_explicit_specialization_was_here)
+ << BaseTemplateSpec;
+ } else {
+ Diag(BaseTemplateSpec->getPointOfInstantiation(),
+ diag::note_template_class_instantiation_was_here)
+ << BaseTemplateSpec;
+ }
+}
+
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
@@ -4820,9 +4919,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
- if (Record->isDynamicClass() && !Record->isDependentType())
- DynamicClasses.push_back(Record);
-
if (Record->getIdentifier()) {
// C++ [class.mem]p13:
// If T is the name of a class, then each of the following shall have a
@@ -4923,7 +5019,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// have inheriting constructors.
DeclareInheritingConstructors(Record);
- checkDLLAttribute(*this, Record);
+ checkClassLevelDLLAttribute(Record);
}
/// Look up the special member function that would be called by a special
@@ -7318,7 +7414,7 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
StdInitializerList = Template;
}
- if (Template != StdInitializerList)
+ if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl())
return false;
// This is an instance of std::initializer_list. Find the argument type.
@@ -8029,15 +8125,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
if (RequireCompleteDeclContext(SS, LookupContext))
return BuildInvalid();
- // The normal rules do not apply to inheriting constructor declarations.
- if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- UsingDecl *UD = BuildValid();
- CheckInheritingConstructorUsingDecl(UD);
- return UD;
- }
-
- // Otherwise, look up the target name.
-
+ // Look up the target name.
LookupResult R(*this, NameInfo, LookupOrdinaryName);
// Unlike most lookups, we don't always want to hide tag
@@ -8056,8 +8144,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
LookupQualifiedName(R, LookupContext);
- // Try to correct typos if possible.
- if (R.empty()) {
+ // Try to correct typos if possible. If constructor name lookup finds no
+ // results, that means the named class has no explicit constructors, and we
+ // suppressed declaring implicit ones (probably because it's dependent or
+ // invalid).
+ if (R.empty() &&
+ NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) {
if (TypoCorrection Corrected = CorrectTypo(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
llvm::make_unique<UsingValidatorCCC>(
@@ -8087,16 +8179,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Context.getRecordType(RD))));
NameInfo.setNamedTypeInfo(nullptr);
-
- // Build it and process it as an inheriting constructor.
- UsingDecl *UD = BuildValid();
- CheckInheritingConstructorUsingDecl(UD);
- return UD;
+ for (auto *Ctor : LookupConstructors(RD))
+ R.addDecl(Ctor);
+ } else {
+ // FIXME: Pick up all the declarations if we found an overloaded function.
+ R.addDecl(ND);
}
-
- // FIXME: Pick up all the declarations if we found an overloaded function.
- R.setLookupName(Corrected.getCorrection());
- R.addDecl(ND);
} else {
Diag(IdentLoc, diag::err_no_member)
<< NameInfo.getName() << LookupContext << SS.getRange();
@@ -8136,6 +8224,18 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
UsingDecl *UD = BuildValid();
+
+ // The normal rules do not apply to inheriting constructor declarations.
+ if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+ // Suppress access diagnostics; the access check is instead performed at the
+ // point of use for an inheriting constructor.
+ R.suppressDiagnostics();
+ CheckInheritingConstructorUsingDecl(UD);
+ return UD;
+ }
+
+ // Otherwise, look up the target name.
+
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
UsingShadowDecl *PrevDecl = nullptr;
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
@@ -8421,7 +8521,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
SourceLocation UsingLoc,
UnqualifiedId &Name,
AttributeList *AttrList,
- TypeResult Type) {
+ TypeResult Type,
+ Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
while (S->getFlags() & Scope::TemplateParamScope)
S = S->getParent();
@@ -8549,6 +8650,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
NewND = NewDecl;
} else {
+ if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) {
+ setTagNameForLinkagePurposes(TD, NewTD);
+ handleTagNumbering(TD, S);
+ }
ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
NewND = NewTD;
}
@@ -9014,7 +9119,7 @@ private:
ASTContext &Context = SemaRef.Context;
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Context.getRecordType(Base)));
- DeclContext::lookup_const_result Decls = Derived->lookup(Name);
+ DeclContext::lookup_result Decls = Derived->lookup(Name);
return Decls.empty() ? Derived->getLocation() : Decls[0]->getLocation();
}
@@ -9363,6 +9468,45 @@ void Sema::ActOnFinishCXXMemberDecls() {
}
}
+static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
+ // Don't do anything for template patterns.
+ if (Class->getDescribedClassTemplate())
+ return;
+
+ for (Decl *Member : Class->decls()) {
+ auto *CD = dyn_cast<CXXConstructorDecl>(Member);
+ if (!CD) {
+ // Recurse on nested classes.
+ if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member))
+ getDefaultArgExprsForConstructors(S, NestedRD);
+ continue;
+ } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) {
+ continue;
+ }
+
+ for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) {
+ // Skip any default arguments that we've already instantiated.
+ if (S.Context.getDefaultArgExprForConstructor(CD, I))
+ continue;
+
+ Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD,
+ CD->getParamDecl(I)).get();
+ S.DiscardCleanupsInEvaluationContext();
+ S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
+ }
+ }
+}
+
+void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) {
+ auto *RD = dyn_cast<CXXRecordDecl>(D);
+
+ // Default constructors that are annotated with __declspec(dllexport) which
+ // have default arguments or don't use the standard calling convention are
+ // wrapped with a thunk called the default constructor closure.
+ if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
+ getDefaultArgExprsForConstructors(*this, RD);
+}
+
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
CXXDestructorDecl *Destructor) {
assert(getLangOpts().CPlusPlus11 &&
@@ -9397,8 +9541,8 @@ namespace {
// copy/move operators. These classes serve as factory functions and help us
// avoid using the same Expr* in the AST twice.
class ExprBuilder {
- ExprBuilder(const ExprBuilder&) LLVM_DELETED_FUNCTION;
- ExprBuilder &operator=(const ExprBuilder&) LLVM_DELETED_FUNCTION;
+ ExprBuilder(const ExprBuilder&) = delete;
+ ExprBuilder &operator=(const ExprBuilder&) = delete;
protected:
static Expr *assertNotNull(Expr *E) {
@@ -10101,7 +10245,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Assign non-static members.
for (auto *Field : ClassDecl->fields()) {
- if (Field->isUnnamedBitfield())
+ // FIXME: We should form some kind of AST representation for the implied
+ // memcpy in a union copy operation.
+ if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
continue;
if (Field->isInvalidDecl()) {
@@ -10531,7 +10677,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Assign non-static members.
for (auto *Field : ClassDecl->fields()) {
- if (Field->isUnnamedBitfield())
+ // FIXME: We should form some kind of AST representation for the implied
+ // memcpy in a union copy operation.
+ if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
continue;
if (Field->isInvalidDecl()) {
@@ -11881,7 +12029,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
//
// We just pretend to initialize the object with itself, then make sure
// it can be destroyed later.
- QualType initType = ExDeclType;
+ QualType initType = Context.getExceptionObjectType(ExDeclType);
InitializedEntity entity =
InitializedEntity::InitializeVariable(ExDecl);
@@ -12739,8 +12887,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
}
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
- for (Stmt::child_range CI = S->children(); CI; ++CI) {
- Stmt *SubStmt = *CI;
+ for (Stmt *SubStmt : S->children()) {
if (!SubStmt)
continue;
if (isa<ReturnStmt>(SubStmt))
@@ -12909,6 +13056,15 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
return true;
}
+void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
+ if (D->getFriendObjectKind())
+ Diag(D->getLocation(), diag::err_pure_friend);
+ else if (auto *M = dyn_cast<CXXMethodDecl>(D))
+ CheckPureMethod(M, ZeroLoc);
+ else
+ Diag(D->getLocation(), diag::err_illegal_initializer);
+}
+
/// \brief Determine whether the given declaration is a static data member.
static bool isStaticDataMember(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
@@ -13122,7 +13278,8 @@ bool Sema::DefineUsedVTables() {
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
- Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
+ if (VTablesUsed[Canonical])
+ Consumer.HandleVTable(Class);
// Optionally warn if we're emitting a weak vtable.
if (Class->isExternallyVisible() &&
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index 7e3da94..f42c4b7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -20,12 +20,15 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "TypeLocBuilder.h"
using namespace clang;
@@ -448,10 +451,437 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
}
+static void diagnoseUseOfProtocols(Sema &TheSema,
+ ObjCContainerDecl *CD,
+ ObjCProtocolDecl *const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs) {
+ assert(ProtoRefs);
+ // Diagnose availability in the context of the ObjC container.
+ Sema::ContextRAII SavedContext(TheSema, CD);
+ for (unsigned i = 0; i < NumProtoRefs; ++i) {
+ (void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i]);
+ }
+}
+
+void Sema::
+ActOnSuperClassOfClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
+ ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange) {
+ // Check if a different kind of symbol declared in this scope.
+ NamedDecl *PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
+ LookupOrdinaryName);
+
+ if (!PrevDecl) {
+ // Try to correct for a typo in the superclass name without correcting
+ // to the class we're defining.
+ if (TypoCorrection Corrected = CorrectTypo(
+ DeclarationNameInfo(SuperName, SuperLoc),
+ LookupOrdinaryName, TUScope,
+ NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
+ CTK_ErrorRecovery)) {
+ diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
+ << SuperName << ClassName);
+ PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
+ }
+ }
+
+ if (declaresSameEntity(PrevDecl, IDecl)) {
+ Diag(SuperLoc, diag::err_recursive_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ IDecl->setEndOfDefinitionLoc(ClassLoc);
+ } else {
+ ObjCInterfaceDecl *SuperClassDecl =
+ dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ QualType SuperClassType;
+
+ // Diagnose classes that inherit from deprecated classes.
+ if (SuperClassDecl) {
+ (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+ SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
+ }
+
+ if (PrevDecl && SuperClassDecl == 0) {
+ // The previous declaration was not a class decl. Check if we have a
+ // typedef. If we do, get the underlying class type.
+ if (const TypedefNameDecl *TDecl =
+ dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+ QualType T = TDecl->getUnderlyingType();
+ if (T->isObjCObjectType()) {
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ SuperClassType = Context.getTypeDeclType(TDecl);
+
+ // This handles the following case:
+ // @interface NewI @end
+ // typedef NewI DeprI __attribute__((deprecated("blah")))
+ // @interface SI : DeprI /* warn here */ @end
+ (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
+ }
+ }
+ }
+
+ // This handles the following case:
+ //
+ // typedef int SuperClass;
+ // @interface MyClass : SuperClass {} @end
+ //
+ if (!SuperClassDecl) {
+ Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ }
+ }
+
+ if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+ if (!SuperClassDecl)
+ Diag(SuperLoc, diag::err_undef_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ else if (RequireCompleteType(SuperLoc,
+ SuperClassType,
+ diag::err_forward_superclass,
+ SuperClassDecl->getDeclName(),
+ ClassName,
+ SourceRange(AtInterfaceLoc, ClassLoc))) {
+ SuperClassDecl = 0;
+ SuperClassType = QualType();
+ }
+ }
+
+ if (SuperClassType.isNull()) {
+ assert(!SuperClassDecl && "Failed to set SuperClassType?");
+ return;
+ }
+
+ // Handle type arguments on the superclass.
+ TypeSourceInfo *SuperClassTInfo = nullptr;
+ if (!SuperTypeArgs.empty()) {
+ TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(
+ S,
+ SuperLoc,
+ CreateParsedType(SuperClassType,
+ nullptr),
+ SuperTypeArgsRange.getBegin(),
+ SuperTypeArgs,
+ SuperTypeArgsRange.getEnd(),
+ SourceLocation(),
+ { },
+ { },
+ SourceLocation());
+ if (!fullSuperClassType.isUsable())
+ return;
+
+ SuperClassType = GetTypeFromParser(fullSuperClassType.get(),
+ &SuperClassTInfo);
+ }
+
+ if (!SuperClassTInfo) {
+ SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
+ SuperLoc);
+ }
+
+ IDecl->setSuperClass(SuperClassTInfo);
+ IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getLocEnd());
+ }
+}
+
+DeclResult Sema::actOnObjCTypeParam(Scope *S,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ IdentifierInfo *paramName,
+ SourceLocation paramLoc,
+ SourceLocation colonLoc,
+ ParsedType parsedTypeBound) {
+ // If there was an explicitly-provided type bound, check it.
+ TypeSourceInfo *typeBoundInfo = nullptr;
+ if (parsedTypeBound) {
+ // The type bound can be any Objective-C pointer type.
+ QualType typeBound = GetTypeFromParser(parsedTypeBound, &typeBoundInfo);
+ if (typeBound->isObjCObjectPointerType()) {
+ // okay
+ } else if (typeBound->isObjCObjectType()) {
+ // The user forgot the * on an Objective-C pointer type, e.g.,
+ // "T : NSView".
+ SourceLocation starLoc = PP.getLocForEndOfToken(
+ typeBoundInfo->getTypeLoc().getEndLoc());
+ Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
+ diag::err_objc_type_param_bound_missing_pointer)
+ << typeBound << paramName
+ << FixItHint::CreateInsertion(starLoc, " *");
+
+ // Create a new type location builder so we can update the type
+ // location information we have.
+ TypeLocBuilder builder;
+ builder.pushFullCopy(typeBoundInfo->getTypeLoc());
+
+ // Create the Objective-C pointer type.
+ typeBound = Context.getObjCObjectPointerType(typeBound);
+ ObjCObjectPointerTypeLoc newT
+ = builder.push<ObjCObjectPointerTypeLoc>(typeBound);
+ newT.setStarLoc(starLoc);
+
+ // Form the new type source information.
+ typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);
+ } else {
+ // Not a valid type bound.
+ Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
+ diag::err_objc_type_param_bound_nonobject)
+ << typeBound << paramName;
+
+ // Forget the bound; we'll default to id later.
+ typeBoundInfo = nullptr;
+ }
+
+ // Type bounds cannot have explicit nullability.
+ if (typeBoundInfo) {
+ // Type arguments cannot explicitly specify nullability.
+ if (auto nullability = AttributedType::stripOuterNullability(typeBound)) {
+ // Look at the type location information to find the nullability
+ // specifier so we can zap it.
+ SourceLocation nullabilityLoc
+ = typeBoundInfo->getTypeLoc().findNullabilityLoc();
+ SourceLocation diagLoc
+ = nullabilityLoc.isValid()? nullabilityLoc
+ : typeBoundInfo->getTypeLoc().getLocStart();
+ Diag(diagLoc, diag::err_type_param_bound_explicit_nullability)
+ << paramName << typeBoundInfo->getType()
+ << FixItHint::CreateRemoval(nullabilityLoc);
+ }
+ }
+ }
+
+ // If there was no explicit type bound (or we removed it due to an error),
+ // use 'id' instead.
+ if (!typeBoundInfo) {
+ colonLoc = SourceLocation();
+ typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType());
+ }
+
+ // Create the type parameter.
+ return ObjCTypeParamDecl::Create(Context, CurContext, variance, varianceLoc,
+ index, paramLoc, paramName, colonLoc,
+ typeBoundInfo);
+}
+
+ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S,
+ SourceLocation lAngleLoc,
+ ArrayRef<Decl *> typeParamsIn,
+ SourceLocation rAngleLoc) {
+ // We know that the array only contains Objective-C type parameters.
+ ArrayRef<ObjCTypeParamDecl *>
+ typeParams(
+ reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()),
+ typeParamsIn.size());
+
+ // Diagnose redeclarations of type parameters.
+ // We do this now because Objective-C type parameters aren't pushed into
+ // scope until later (after the instance variable block), but we want the
+ // diagnostics to occur right after we parse the type parameter list.
+ llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams;
+ for (auto typeParam : typeParams) {
+ auto known = knownParams.find(typeParam->getIdentifier());
+ if (known != knownParams.end()) {
+ Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl)
+ << typeParam->getIdentifier()
+ << SourceRange(known->second->getLocation());
+
+ typeParam->setInvalidDecl();
+ } else {
+ knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam));
+
+ // Push the type parameter into scope.
+ PushOnScopeChains(typeParam, S, /*AddToContext=*/false);
+ }
+ }
+
+ // Create the parameter list.
+ return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc);
+}
+
+void Sema::popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList) {
+ for (auto typeParam : *typeParamList) {
+ if (!typeParam->isInvalidDecl()) {
+ S->RemoveDecl(typeParam);
+ IdResolver.RemoveDecl(typeParam);
+ }
+ }
+}
+
+namespace {
+ /// The context in which an Objective-C type parameter list occurs, for use
+ /// in diagnostics.
+ enum class TypeParamListContext {
+ ForwardDeclaration,
+ Definition,
+ Category,
+ Extension
+ };
+}
+
+/// Check consistency between two Objective-C type parameter lists, e.g.,
+/// between a category/extension and an \@interface or between an \@class and an
+/// \@interface.
+static bool checkTypeParamListConsistency(Sema &S,
+ ObjCTypeParamList *prevTypeParams,
+ ObjCTypeParamList *newTypeParams,
+ TypeParamListContext newContext) {
+ // If the sizes don't match, complain about that.
+ if (prevTypeParams->size() != newTypeParams->size()) {
+ SourceLocation diagLoc;
+ if (newTypeParams->size() > prevTypeParams->size()) {
+ diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
+ } else {
+ diagLoc = S.PP.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
+ }
+
+ S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
+ << static_cast<unsigned>(newContext)
+ << (newTypeParams->size() > prevTypeParams->size())
+ << prevTypeParams->size()
+ << newTypeParams->size();
+
+ return true;
+ }
+
+ // Match up the type parameters.
+ for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) {
+ ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i];
+ ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i];
+
+ // Check for consistency of the variance.
+ if (newTypeParam->getVariance() != prevTypeParam->getVariance()) {
+ if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant &&
+ newContext != TypeParamListContext::Definition) {
+ // When the new type parameter is invariant and is not part
+ // of the definition, just propagate the variance.
+ newTypeParam->setVariance(prevTypeParam->getVariance());
+ } else if (prevTypeParam->getVariance()
+ == ObjCTypeParamVariance::Invariant &&
+ !(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&
+ cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())
+ ->getDefinition() == prevTypeParam->getDeclContext())) {
+ // When the old parameter is invariant and was not part of the
+ // definition, just ignore the difference because it doesn't
+ // matter.
+ } else {
+ {
+ // Diagnose the conflict and update the second declaration.
+ SourceLocation diagLoc = newTypeParam->getVarianceLoc();
+ if (diagLoc.isInvalid())
+ diagLoc = newTypeParam->getLocStart();
+
+ auto diag = S.Diag(diagLoc,
+ diag::err_objc_type_param_variance_conflict)
+ << static_cast<unsigned>(newTypeParam->getVariance())
+ << newTypeParam->getDeclName()
+ << static_cast<unsigned>(prevTypeParam->getVariance())
+ << prevTypeParam->getDeclName();
+ switch (prevTypeParam->getVariance()) {
+ case ObjCTypeParamVariance::Invariant:
+ diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc());
+ break;
+
+ case ObjCTypeParamVariance::Covariant:
+ case ObjCTypeParamVariance::Contravariant: {
+ StringRef newVarianceStr
+ = prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant
+ ? "__covariant"
+ : "__contravariant";
+ if (newTypeParam->getVariance()
+ == ObjCTypeParamVariance::Invariant) {
+ diag << FixItHint::CreateInsertion(newTypeParam->getLocStart(),
+ (newVarianceStr + " ").str());
+ } else {
+ diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),
+ newVarianceStr);
+ }
+ }
+ }
+ }
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+
+ // Override the variance.
+ newTypeParam->setVariance(prevTypeParam->getVariance());
+ }
+ }
+
+ // If the bound types match, there's nothing to do.
+ if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(),
+ newTypeParam->getUnderlyingType()))
+ continue;
+
+ // If the new type parameter's bound was explicit, complain about it being
+ // different from the original.
+ if (newTypeParam->hasExplicitBound()) {
+ SourceRange newBoundRange = newTypeParam->getTypeSourceInfo()
+ ->getTypeLoc().getSourceRange();
+ S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict)
+ << newTypeParam->getUnderlyingType()
+ << newTypeParam->getDeclName()
+ << prevTypeParam->hasExplicitBound()
+ << prevTypeParam->getUnderlyingType()
+ << (newTypeParam->getDeclName() == prevTypeParam->getDeclName())
+ << prevTypeParam->getDeclName()
+ << FixItHint::CreateReplacement(
+ newBoundRange,
+ prevTypeParam->getUnderlyingType().getAsString(
+ S.Context.getPrintingPolicy()));
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+
+ // Override the new type parameter's bound type with the previous type,
+ // so that it's consistent.
+ newTypeParam->setTypeSourceInfo(
+ S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));
+ continue;
+ }
+
+ // The new type parameter got the implicit bound of 'id'. That's okay for
+ // categories and extensions (overwrite it later), but not for forward
+ // declarations and @interfaces, because those must be standalone.
+ if (newContext == TypeParamListContext::ForwardDeclaration ||
+ newContext == TypeParamListContext::Definition) {
+ // Diagnose this problem for forward declarations and definitions.
+ SourceLocation insertionLoc
+ = S.PP.getLocForEndOfToken(newTypeParam->getLocation());
+ std::string newCode
+ = " : " + prevTypeParam->getUnderlyingType().getAsString(
+ S.Context.getPrintingPolicy());
+ S.Diag(newTypeParam->getLocation(),
+ diag::err_objc_type_param_bound_missing)
+ << prevTypeParam->getUnderlyingType()
+ << newTypeParam->getDeclName()
+ << (newContext == TypeParamListContext::ForwardDeclaration)
+ << FixItHint::CreateInsertion(insertionLoc, newCode);
+
+ S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
+ << prevTypeParam->getDeclName();
+ }
+
+ // Update the new type parameter's bound to match the previous one.
+ newTypeParam->setTypeSourceInfo(
+ S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));
+ }
+
+ return false;
+}
+
Decl *Sema::
-ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+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) {
@@ -485,10 +915,50 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
ClassName = PrevIDecl->getIdentifier();
}
+ // If there was a forward declaration with type parameters, check
+ // for consistency.
+ if (PrevIDecl) {
+ if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {
+ if (typeParamList) {
+ // Both have type parameter lists; check for consistency.
+ if (checkTypeParamListConsistency(*this, prevTypeParamList,
+ typeParamList,
+ TypeParamListContext::Definition)) {
+ typeParamList = nullptr;
+ }
+ } else {
+ Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first)
+ << ClassName;
+ Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl)
+ << ClassName;
+
+ // Clone the type parameter list.
+ SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams;
+ for (auto typeParam : *prevTypeParamList) {
+ clonedTypeParams.push_back(
+ ObjCTypeParamDecl::Create(
+ Context,
+ CurContext,
+ typeParam->getVariance(),
+ SourceLocation(),
+ typeParam->getIndex(),
+ SourceLocation(),
+ typeParam->getIdentifier(),
+ SourceLocation(),
+ Context.getTrivialTypeSourceInfo(typeParam->getUnderlyingType())));
+ }
+
+ typeParamList = ObjCTypeParamList::create(Context,
+ SourceLocation(),
+ clonedTypeParams,
+ SourceLocation());
+ }
+ }
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
- PrevIDecl, ClassLoc);
-
+ typeParamList, PrevIDecl, ClassLoc);
if (PrevIDecl) {
// Class already seen. Was it a definition?
if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
@@ -509,88 +979,21 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->startDefinition();
if (SuperName) {
- // Check if a different kind of symbol declared in this scope.
- PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
- LookupOrdinaryName);
+ // Diagnose availability in the context of the @interface.
+ ContextRAII SavedContext(*this, IDecl);
- if (!PrevDecl) {
- // Try to correct for a typo in the superclass name without correcting
- // to the class we're defining.
- if (TypoCorrection Corrected =
- CorrectTypo(DeclarationNameInfo(SuperName, SuperLoc),
- LookupOrdinaryName, TUScope, nullptr,
- llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
- CTK_ErrorRecovery)) {
- diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
- << SuperName << ClassName);
- PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
- }
- }
-
- if (declaresSameEntity(PrevDecl, IDecl)) {
- Diag(SuperLoc, diag::err_recursive_superclass)
- << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
- IDecl->setEndOfDefinitionLoc(ClassLoc);
- } else {
- ObjCInterfaceDecl *SuperClassDecl =
- dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
-
- // Diagnose classes that inherit from deprecated classes.
- if (SuperClassDecl)
- (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
-
- if (PrevDecl && !SuperClassDecl) {
- // The previous declaration was not a class decl. Check if we have a
- // typedef. If we do, get the underlying class type.
- if (const TypedefNameDecl *TDecl =
- dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
- QualType T = TDecl->getUnderlyingType();
- if (T->isObjCObjectType()) {
- if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
- SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
- // This handles the following case:
- // @interface NewI @end
- // typedef NewI DeprI __attribute__((deprecated("blah")))
- // @interface SI : DeprI /* warn here */ @end
- (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
- }
- }
- }
-
- // This handles the following case:
- //
- // typedef int SuperClass;
- // @interface MyClass : SuperClass {} @end
- //
- if (!SuperClassDecl) {
- Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- }
- }
-
- if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
- if (!SuperClassDecl)
- Diag(SuperLoc, diag::err_undef_superclass)
- << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
- else if (RequireCompleteType(SuperLoc,
- Context.getObjCInterfaceType(SuperClassDecl),
- diag::err_forward_superclass,
- SuperClassDecl->getDeclName(),
- ClassName,
- SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = nullptr;
- }
- }
- IDecl->setSuperClass(SuperClassDecl);
- IDecl->setSuperClassLoc(SuperLoc);
- IDecl->setEndOfDefinitionLoc(SuperLoc);
- }
+ ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
+ ClassName, ClassLoc,
+ SuperName, SuperLoc, SuperTypeArgs,
+ SuperTypeArgsRange);
} else { // we have a root class.
IDecl->setEndOfDefinitionLoc(ClassLoc);
}
// Check then save referenced protocols.
if (NumProtoRefs) {
+ diagnoseUseOfProtocols(*this, IDecl, (ObjCProtocolDecl*const*)ProtoRefs,
+ NumProtoRefs, ProtoLocs);
IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
ProtoLocs, Context);
IDecl->setEndOfDefinitionLoc(EndProtoLoc);
@@ -617,8 +1020,7 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType())
if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>())
- for (auto *I : OPT->quals())
- ProtocolRefs.push_back(I);
+ ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());
}
}
@@ -752,6 +1154,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
if (!err && NumProtoRefs ) {
/// Check then save referenced protocols.
+ diagnoseUseOfProtocols(*this, PDecl, (ObjCProtocolDecl*const*)ProtoRefs,
+ NumProtoRefs, ProtoLocs);
PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
ProtoLocs, Context);
}
@@ -779,7 +1183,7 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
/// issues an error if they are not declared. It returns list of
/// protocol declarations in its 'Protocols' argument.
void
-Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
+Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
const IdentifierLocPair *ProtocolId,
unsigned NumProtocols,
SmallVectorImpl<Decl *> &Protocols) {
@@ -805,8 +1209,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
// If this is a forward protocol declaration, get its definition.
if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())
PDecl = PDecl->getDefinition();
-
- (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+
+ // For an objc container, delay protocol reference checking until after we
+ // can set the objc decl as the availability context, otherwise check now.
+ if (!ForObjCContainer) {
+ (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+ }
// If this is a forward declaration and we are supposed to warn in this
// case, do it.
@@ -824,6 +1232,400 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
}
}
+namespace {
+// Callback to only accept typo corrections that are either
+// Objective-C protocols or valid Objective-C type arguments.
+class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback {
+ ASTContext &Context;
+ Sema::LookupNameKind LookupKind;
+ public:
+ ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,
+ Sema::LookupNameKind lookupKind)
+ : Context(context), LookupKind(lookupKind) { }
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ // If we're allowed to find protocols and we have a protocol, accept it.
+ if (LookupKind != Sema::LookupOrdinaryName) {
+ if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())
+ return true;
+ }
+
+ // If we're allowed to find type names and we have one, accept it.
+ if (LookupKind != Sema::LookupObjCProtocolName) {
+ // If we have a type declaration, we might accept this result.
+ if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {
+ // If we found a tag declaration outside of C++, skip it. This
+ // can happy because we look for any name when there is no
+ // bias to protocol or type names.
+ if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)
+ return false;
+
+ // Make sure the type is something we would accept as a type
+ // argument.
+ auto type = Context.getTypeDeclType(typeDecl);
+ if (type->isObjCObjectPointerType() ||
+ type->isBlockPointerType() ||
+ type->isDependentType() ||
+ type->isObjCObjectType())
+ return true;
+
+ return false;
+ }
+
+ // If we have an Objective-C class type, accept it; there will
+ // be another fix to add the '*'.
+ if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())
+ return true;
+
+ return false;
+ }
+
+ return false;
+ }
+};
+} // end anonymous namespace
+
+void Sema::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) {
+ // Local function that updates the declaration specifiers with
+ // protocol information.
+ unsigned numProtocolsResolved = 0;
+ auto resolvedAsProtocols = [&] {
+ assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");
+
+ // Determine whether the base type is a parameterized class, in
+ // which case we want to warn about typos such as
+ // "NSArray<NSObject>" (that should be NSArray<NSObject *>).
+ ObjCInterfaceDecl *baseClass = nullptr;
+ QualType base = GetTypeFromParser(baseType, nullptr);
+ bool allAreTypeNames = false;
+ SourceLocation firstClassNameLoc;
+ if (!base.isNull()) {
+ if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) {
+ baseClass = objcObjectType->getInterface();
+ if (baseClass) {
+ if (auto typeParams = baseClass->getTypeParamList()) {
+ if (typeParams->size() == numProtocolsResolved) {
+ // Note that we should be looking for type names, too.
+ allAreTypeNames = true;
+ }
+ }
+ }
+ }
+ }
+
+ for (unsigned i = 0, n = protocols.size(); i != n; ++i) {
+ ObjCProtocolDecl *&proto
+ = reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]);
+ // For an objc container, delay protocol reference checking until after we
+ // can set the objc decl as the availability context, otherwise check now.
+ if (!warnOnIncompleteProtocols) {
+ (void)DiagnoseUseOfDecl(proto, identifierLocs[i]);
+ }
+
+ // If this is a forward protocol declaration, get its definition.
+ if (!proto->isThisDeclarationADefinition() && proto->getDefinition())
+ proto = proto->getDefinition();
+
+ // If this is a forward declaration and we are supposed to warn in this
+ // case, do it.
+ // FIXME: Recover nicely in the hidden case.
+ ObjCProtocolDecl *forwardDecl = nullptr;
+ if (warnOnIncompleteProtocols &&
+ NestedProtocolHasNoDefinition(proto, forwardDecl)) {
+ Diag(identifierLocs[i], diag::warn_undef_protocolref)
+ << proto->getDeclName();
+ Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)
+ << forwardDecl;
+ }
+
+ // If everything this far has been a type name (and we care
+ // about such things), check whether this name refers to a type
+ // as well.
+ if (allAreTypeNames) {
+ if (auto *decl = LookupSingleName(S, identifiers[i], identifierLocs[i],
+ LookupOrdinaryName)) {
+ if (isa<ObjCInterfaceDecl>(decl)) {
+ if (firstClassNameLoc.isInvalid())
+ firstClassNameLoc = identifierLocs[i];
+ } else if (!isa<TypeDecl>(decl)) {
+ // Not a type.
+ allAreTypeNames = false;
+ }
+ } else {
+ allAreTypeNames = false;
+ }
+ }
+ }
+
+ // All of the protocols listed also have type names, and at least
+ // one is an Objective-C class name. Check whether all of the
+ // protocol conformances are declared by the base class itself, in
+ // which case we warn.
+ if (allAreTypeNames && firstClassNameLoc.isValid()) {
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols;
+ Context.CollectInheritedProtocols(baseClass, knownProtocols);
+ bool allProtocolsDeclared = true;
+ for (auto proto : protocols) {
+ if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) {
+ allProtocolsDeclared = false;
+ break;
+ }
+ }
+
+ if (allProtocolsDeclared) {
+ Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)
+ << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(firstClassNameLoc), " *");
+ }
+ }
+
+ protocolLAngleLoc = lAngleLoc;
+ protocolRAngleLoc = rAngleLoc;
+ assert(protocols.size() == identifierLocs.size());
+ };
+
+ // Attempt to resolve all of the identifiers as protocols.
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);
+ protocols.push_back(proto);
+ if (proto)
+ ++numProtocolsResolved;
+ }
+
+ // If all of the names were protocols, these were protocol qualifiers.
+ if (numProtocolsResolved == identifiers.size())
+ return resolvedAsProtocols();
+
+ // Attempt to resolve all of the identifiers as type names or
+ // Objective-C class names. The latter is technically ill-formed,
+ // but is probably something like \c NSArray<NSView *> missing the
+ // \c*.
+ typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;
+ SmallVector<TypeOrClassDecl, 4> typeDecls;
+ unsigned numTypeDeclsResolved = 0;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ NamedDecl *decl = LookupSingleName(S, identifiers[i], identifierLocs[i],
+ LookupOrdinaryName);
+ if (!decl) {
+ typeDecls.push_back(TypeOrClassDecl());
+ continue;
+ }
+
+ if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
+ typeDecls.push_back(typeDecl);
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {
+ typeDecls.push_back(objcClass);
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ typeDecls.push_back(TypeOrClassDecl());
+ }
+
+ AttributeFactory attrFactory;
+
+ // Local function that forms a reference to the given type or
+ // Objective-C class declaration.
+ auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
+ -> TypeResult {
+ // Form declaration specifiers. They simply refer to the type.
+ DeclSpec DS(attrFactory);
+ const char* prevSpec; // unused
+ unsigned diagID; // unused
+ QualType type;
+ if (auto *actualTypeDecl = typeDecl.dyn_cast<TypeDecl *>())
+ type = Context.getTypeDeclType(actualTypeDecl);
+ else
+ type = Context.getObjCInterfaceType(typeDecl.get<ObjCInterfaceDecl *>());
+ TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);
+ ParsedType parsedType = CreateParsedType(type, parsedTSInfo);
+ DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,
+ parsedType, Context.getPrintingPolicy());
+ // Use the identifier location for the type source range.
+ DS.SetRangeStart(loc);
+ DS.SetRangeEnd(loc);
+
+ // Form the declarator.
+ Declarator D(DS, Declarator::TypeNameContext);
+
+ // If we have a typedef of an Objective-C class type that is missing a '*',
+ // add the '*'.
+ if (type->getAs<ObjCInterfaceType>()) {
+ SourceLocation starLoc = PP.getLocForEndOfToken(loc);
+ ParsedAttributes parsedAttrs(attrFactory);
+ D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
+ SourceLocation(),
+ SourceLocation(),
+ SourceLocation(),
+ SourceLocation()),
+ parsedAttrs,
+ starLoc);
+
+ // Diagnose the missing '*'.
+ Diag(loc, diag::err_objc_type_arg_missing_star)
+ << type
+ << FixItHint::CreateInsertion(starLoc, " *");
+ }
+
+ // Convert this to a type.
+ return ActOnTypeName(S, D);
+ };
+
+ // Local function that updates the declaration specifiers with
+ // type argument information.
+ auto resolvedAsTypeDecls = [&] {
+ // We did not resolve these as protocols.
+ protocols.clear();
+
+ assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl");
+ // Map type declarations to type arguments.
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ // Map type reference to a type.
+ TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]);
+ if (!type.isUsable()) {
+ typeArgs.clear();
+ return;
+ }
+
+ typeArgs.push_back(type.get());
+ }
+
+ typeArgsLAngleLoc = lAngleLoc;
+ typeArgsRAngleLoc = rAngleLoc;
+ };
+
+ // If all of the identifiers can be resolved as type names or
+ // Objective-C class names, we have type arguments.
+ if (numTypeDeclsResolved == identifiers.size())
+ return resolvedAsTypeDecls();
+
+ // Error recovery: some names weren't found, or we have a mix of
+ // type and protocol names. Go resolve all of the unresolved names
+ // and complain if we can't find a consistent answer.
+ LookupNameKind lookupKind = LookupAnyName;
+ for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
+ // If we already have a protocol or type. Check whether it is the
+ // right thing.
+ if (protocols[i] || typeDecls[i]) {
+ // If we haven't figured out whether we want types or protocols
+ // yet, try to figure it out from this name.
+ if (lookupKind == LookupAnyName) {
+ // If this name refers to both a protocol and a type (e.g., \c
+ // NSObject), don't conclude anything yet.
+ if (protocols[i] && typeDecls[i])
+ continue;
+
+ // Otherwise, let this name decide whether we'll be correcting
+ // toward types or protocols.
+ lookupKind = protocols[i] ? LookupObjCProtocolName
+ : LookupOrdinaryName;
+ continue;
+ }
+
+ // If we want protocols and we have a protocol, there's nothing
+ // more to do.
+ if (lookupKind == LookupObjCProtocolName && protocols[i])
+ continue;
+
+ // If we want types and we have a type declaration, there's
+ // nothing more to do.
+ if (lookupKind == LookupOrdinaryName && typeDecls[i])
+ continue;
+
+ // We have a conflict: some names refer to protocols and others
+ // refer to types.
+ Diag(identifierLocs[i], diag::err_objc_type_args_and_protocols)
+ << (protocols[i] != nullptr)
+ << identifiers[i]
+ << identifiers[0]
+ << SourceRange(identifierLocs[0]);
+
+ protocols.clear();
+ typeArgs.clear();
+ return;
+ }
+
+ // Perform typo correction on the name.
+ TypoCorrection corrected = CorrectTypo(
+ DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,
+ nullptr,
+ llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(Context,
+ lookupKind),
+ CTK_ErrorRecovery);
+ if (corrected) {
+ // Did we find a protocol?
+ if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_undeclared_protocol_suggest)
+ << identifiers[i]);
+ lookupKind = LookupObjCProtocolName;
+ protocols[i] = proto;
+ ++numProtocolsResolved;
+ continue;
+ }
+
+ // Did we find a type?
+ if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_unknown_typename_suggest)
+ << identifiers[i]);
+ lookupKind = LookupOrdinaryName;
+ typeDecls[i] = typeDecl;
+ ++numTypeDeclsResolved;
+ continue;
+ }
+
+ // Did we find an Objective-C class?
+ if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+ diagnoseTypo(corrected,
+ PDiag(diag::err_unknown_type_or_class_name_suggest)
+ << identifiers[i] << true);
+ lookupKind = LookupOrdinaryName;
+ typeDecls[i] = objcClass;
+ ++numTypeDeclsResolved;
+ continue;
+ }
+ }
+
+ // We couldn't find anything.
+ Diag(identifierLocs[i],
+ (lookupKind == LookupAnyName ? diag::err_objc_type_arg_missing
+ : lookupKind == LookupObjCProtocolName ? diag::err_undeclared_protocol
+ : diag::err_unknown_typename))
+ << identifiers[i];
+ protocols.clear();
+ typeArgs.clear();
+ return;
+ }
+
+ // If all of the names were (corrected to) protocols, these were
+ // protocol qualifiers.
+ if (numProtocolsResolved == identifiers.size())
+ return resolvedAsProtocols();
+
+ // Otherwise, all of the names were (corrected to) types.
+ assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");
+ return resolvedAsTypeDecls();
+}
+
/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
/// a class method in its extension.
///
@@ -884,6 +1686,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
Decl *Sema::
ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
IdentifierInfo *CategoryName,
SourceLocation CategoryLoc,
Decl * const *ProtoRefs,
@@ -903,7 +1706,8 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// the enclosing method declarations. We mark the decl invalid
// to make it clear that this isn't a valid AST.
CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassLoc, CategoryLoc, CategoryName,IDecl);
+ ClassLoc, CategoryLoc, CategoryName,
+ IDecl, typeParamList);
CDecl->setInvalidDecl();
CurContext->addDecl(CDecl);
@@ -929,13 +1733,35 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
}
}
+ // If we have a type parameter list, check it.
+ if (typeParamList) {
+ if (auto prevTypeParamList = IDecl->getTypeParamList()) {
+ if (checkTypeParamListConsistency(*this, prevTypeParamList, typeParamList,
+ CategoryName
+ ? TypeParamListContext::Category
+ : TypeParamListContext::Extension))
+ typeParamList = nullptr;
+ } else {
+ Diag(typeParamList->getLAngleLoc(),
+ diag::err_objc_parameterized_category_nonclass)
+ << (CategoryName != nullptr)
+ << ClassName
+ << typeParamList->getSourceRange();
+
+ typeParamList = nullptr;
+ }
+ }
+
CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassLoc, CategoryLoc, CategoryName, IDecl);
+ ClassLoc, CategoryLoc, CategoryName, IDecl,
+ typeParamList);
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
if (NumProtoRefs) {
- CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
+ diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs,
+ NumProtoRefs, ProtoLocs);
+ CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
ProtoLocs, Context);
// Protocols in the class extension belong to the class.
if (CDecl->IsClassExtension())
@@ -963,7 +1789,8 @@ Decl *Sema::ActOnStartCategoryImplementation(
// Create and install one.
CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc,
ClassLoc, CatLoc,
- CatName, IDecl);
+ CatName, IDecl,
+ /*typeParamList=*/nullptr);
CatIDecl->setImplicit();
}
}
@@ -1077,12 +1904,14 @@ Decl *Sema::ActOnStartClassImplementation(
// FIXME: Do we support attributes on the @implementation? If so we should
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
- ClassName, /*PrevDecl=*/nullptr, ClassLoc,
+ ClassName, /*typeParamList=*/nullptr,
+ /*PrevDecl=*/nullptr, ClassLoc,
true);
IDecl->startDefinition();
if (SDecl) {
- IDecl->setSuperClass(SDecl);
- IDecl->setSuperClassLoc(SuperClassLoc);
+ IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(
+ Context.getObjCInterfaceType(SDecl),
+ SuperClassLoc));
IDecl->setEndOfDefinitionLoc(SuperClassLoc);
} else {
IDecl->setEndOfDefinitionLoc(ClassLoc);
@@ -1342,6 +2171,13 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) {
return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());
}
+/// Determine whether two set of Objective-C declaration qualifiers conflict.
+static bool objcModifiersConflict(Decl::ObjCDeclQualifier x,
+ Decl::ObjCDeclQualifier y) {
+ return (x & ~Decl::OBJC_TQ_CSNullability) !=
+ (y & ~Decl::OBJC_TQ_CSNullability);
+}
+
static bool CheckMethodOverrideReturn(Sema &S,
ObjCMethodDecl *MethodImpl,
ObjCMethodDecl *MethodDecl,
@@ -1349,8 +2185,8 @@ static bool CheckMethodOverrideReturn(Sema &S,
bool IsOverridingMode,
bool Warn) {
if (IsProtocolMethodDecl &&
- (MethodDecl->getObjCDeclQualifier() !=
- MethodImpl->getObjCDeclQualifier())) {
+ objcModifiersConflict(MethodDecl->getObjCDeclQualifier(),
+ MethodImpl->getObjCDeclQualifier())) {
if (Warn) {
S.Diag(MethodImpl->getLocation(),
(IsOverridingMode
@@ -1364,7 +2200,28 @@ static bool CheckMethodOverrideReturn(Sema &S,
else
return false;
}
-
+ if (Warn && IsOverridingMode &&
+ !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
+ !S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),
+ MethodDecl->getReturnType(),
+ false)) {
+ auto nullabilityMethodImpl =
+ *MethodImpl->getReturnType()->getNullability(S.Context);
+ auto nullabilityMethodDecl =
+ *MethodDecl->getReturnType()->getNullability(S.Context);
+ S.Diag(MethodImpl->getLocation(),
+ diag::warn_conflicting_nullability_attr_overriding_ret_types)
+ << DiagNullabilityKind(
+ nullabilityMethodImpl,
+ ((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ nullabilityMethodDecl,
+ ((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
+ }
+
if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),
MethodDecl->getReturnType()))
return true;
@@ -1414,8 +2271,8 @@ static bool CheckMethodOverrideParam(Sema &S,
bool IsOverridingMode,
bool Warn) {
if (IsProtocolMethodDecl &&
- (ImplVar->getObjCDeclQualifier() !=
- IfaceVar->getObjCDeclQualifier())) {
+ objcModifiersConflict(ImplVar->getObjCDeclQualifier(),
+ IfaceVar->getObjCDeclQualifier())) {
if (Warn) {
if (IsOverridingMode)
S.Diag(ImplVar->getLocation(),
@@ -1435,7 +2292,21 @@ static bool CheckMethodOverrideParam(Sema &S,
QualType ImplTy = ImplVar->getType();
QualType IfaceTy = IfaceVar->getType();
-
+ if (Warn && IsOverridingMode &&
+ !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
+ !S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {
+ S.Diag(ImplVar->getLocation(),
+ diag::warn_conflicting_nullability_attr_overriding_param_types)
+ << DiagNullabilityKind(
+ *ImplTy->getNullability(S.Context),
+ ((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ *IfaceTy->getNullability(S.Context),
+ ((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
+ S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
+ }
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return true;
@@ -1964,6 +2835,9 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);
}
+ // Diagnose null-resettable synthesized setters.
+ diagnoseNullResettableSynthesizedSetters(IMPDecl);
+
SelectorSet ClsMap;
for (const auto *I : IMPDecl->class_methods())
ClsMap.insert(I->getSelector());
@@ -2014,6 +2888,7 @@ Sema::DeclGroupPtrTy
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
unsigned NumElts) {
SmallVector<Decl *, 8> DeclsInGroup;
for (unsigned i = 0; i != NumElts; ++i) {
@@ -2068,9 +2943,33 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
ClassName = PrevIDecl->getIdentifier();
}
+ // If this forward declaration has type parameters, compare them with the
+ // type parameters of the previous declaration.
+ ObjCTypeParamList *TypeParams = TypeParamLists[i];
+ if (PrevIDecl && TypeParams) {
+ if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) {
+ // Check for consistency with the previous declaration.
+ if (checkTypeParamListConsistency(
+ *this, PrevTypeParams, TypeParams,
+ TypeParamListContext::ForwardDeclaration)) {
+ TypeParams = nullptr;
+ }
+ } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
+ // The @interface does not have type parameters. Complain.
+ Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class)
+ << ClassName
+ << TypeParams->getSourceRange();
+ Diag(Def->getLocation(), diag::note_defined_here)
+ << ClassName;
+
+ TypeParams = nullptr;
+ }
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
- ClassName, PrevIDecl, IdentLocs[i]);
+ ClassName, TypeParams, PrevIDecl,
+ IdentLocs[i]);
IDecl->setAtEndRange(IdentLocs[i]);
PushOnScopeChains(IDecl, TUScope);
@@ -2241,8 +3140,14 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty())
continue;
- if (!MatchTwoMethodDeclarations(Method, List->getMethod()))
+ if (!MatchTwoMethodDeclarations(Method, List->getMethod())) {
+ // Even if two method types do not match, we would like to say
+ // there is more than one declaration so unavailability/deprecated
+ // warning is not too noisy.
+ if (!Method->isDefined())
+ List->setHasMoreThanOneDecl(true);
continue;
+ }
ObjCMethodDecl *PrevObjCMethod = List->getMethod();
@@ -2341,19 +3246,33 @@ bool Sema::CollectMultipleMethodsInGlobalPool(
return Methods.size() > 1;
}
-bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) {
+bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+ SourceRange R,
+ bool receiverIdOrClass) {
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
// Test for no method in the pool which should not trigger any warning by
// caller.
if (Pos == MethodPool.end())
return true;
- ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+ ObjCMethodList &MethList =
+ BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;
+
+ // Diagnose finding more than one method in global pool
+ SmallVector<ObjCMethodDecl *, 4> Methods;
+ Methods.push_back(BestMethod);
+ for (ObjCMethodList *ML = &MethList; ML; ML = ML->getNext())
+ if (ObjCMethodDecl *M = ML->getMethod())
+ if (!M->isHidden() && M != BestMethod && !M->hasAttr<UnavailableAttr>())
+ Methods.push_back(M);
+ if (Methods.size() > 1)
+ DiagnoseMultipleMethodInGlobalPool(Methods, Sel, R, receiverIdOrClass);
+
return MethList.hasMoreThanOneDecl();
}
ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
bool receiverIdOrClass,
- bool warn, bool instance) {
+ bool instance) {
if (ExternalSource)
ReadMethodPool(Sel);
@@ -2365,31 +3284,23 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
SmallVector<ObjCMethodDecl *, 4> Methods;
for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
- if (M->getMethod() && !M->getMethod()->isHidden()) {
- // If we're not supposed to warn about mismatches, we're done.
- if (!warn)
- return M->getMethod();
-
- Methods.push_back(M->getMethod());
- }
+ if (M->getMethod() && !M->getMethod()->isHidden())
+ return M->getMethod();
}
+ return nullptr;
+}
- // If there aren't any visible methods, we're done.
- // FIXME: Recover if there are any known-but-hidden methods?
- if (Methods.empty())
- return nullptr;
-
- if (Methods.size() == 1)
- return Methods[0];
-
+void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ Selector Sel, SourceRange R,
+ bool receiverIdOrClass) {
// We found multiple methods, so we may have to complain.
bool issueDiagnostic = false, issueError = false;
// We support a warning which complains about *any* difference in
// method signature.
bool strictSelectorMatch =
- receiverIdOrClass && warn &&
- !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
+ receiverIdOrClass &&
+ !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
if (strictSelectorMatch) {
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
@@ -2414,7 +3325,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
break;
}
}
-
+
if (issueDiagnostic) {
if (issueError)
Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
@@ -2422,16 +3333,15 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
else
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
-
+
Diag(Methods[0]->getLocStart(),
issueError ? diag::note_possibility : diag::note_using)
- << Methods[0]->getSourceRange();
+ << Methods[0]->getSourceRange();
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
Diag(Methods[I]->getLocStart(), diag::note_also_found)
- << Methods[I]->getSourceRange();
- }
+ << Methods[I]->getSourceRange();
+ }
}
- return Methods[0];
}
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
@@ -2442,12 +3352,16 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
GlobalMethods &Methods = Pos->second;
for (const ObjCMethodList *Method = &Methods.first; Method;
Method = Method->getNext())
- if (Method->getMethod() && Method->getMethod()->isDefined())
+ if (Method->getMethod() &&
+ (Method->getMethod()->isDefined() ||
+ Method->getMethod()->isPropertyAccessor()))
return Method->getMethod();
for (const ObjCMethodList *Method = &Methods.second; Method;
Method = Method->getNext())
- if (Method->getMethod() && Method->getMethod()->isDefined())
+ if (Method->getMethod() &&
+ (Method->getMethod()->isDefined() ||
+ Method->getMethod()->isPropertyAccessor()))
return Method->getMethod();
return nullptr;
}
@@ -2571,10 +3485,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
case Decl::ObjCProtocol:
return Sema::OCK_Protocol;
case Decl::ObjCCategory:
- if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
+ if (cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
return Sema::OCK_ClassExtension;
- else
- return Sema::OCK_Category;
+ return Sema::OCK_Category;
case Decl::ObjCImplementation:
return Sema::OCK_Implementation;
case Decl::ObjCCategoryImpl:
@@ -3083,6 +3996,89 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol);
}
+/// Merge type nullability from for a redeclaration of the same entity,
+/// producing the updated type of the redeclared entity.
+static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
+ QualType type,
+ bool usesCSKeyword,
+ SourceLocation prevLoc,
+ QualType prevType,
+ bool prevUsesCSKeyword) {
+ // Determine the nullability of both types.
+ auto nullability = type->getNullability(S.Context);
+ auto prevNullability = prevType->getNullability(S.Context);
+
+ // Easy case: both have nullability.
+ if (nullability.hasValue() == prevNullability.hasValue()) {
+ // Neither has nullability; continue.
+ if (!nullability)
+ return type;
+
+ // The nullabilities are equivalent; do nothing.
+ if (*nullability == *prevNullability)
+ return type;
+
+ // Complain about mismatched nullability.
+ S.Diag(loc, diag::err_nullability_conflicting)
+ << DiagNullabilityKind(*nullability, usesCSKeyword)
+ << DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);
+ return type;
+ }
+
+ // If it's the redeclaration that has nullability, don't change anything.
+ if (nullability)
+ return type;
+
+ // Otherwise, provide the result with the same nullability.
+ return S.Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*prevNullability),
+ type, type);
+}
+
+/// Merge information from the declaration of a method in the \@interface
+/// (or a category/extension) into the corresponding method in the
+/// @implementation (for a class or category).
+static void mergeInterfaceMethodToImpl(Sema &S,
+ ObjCMethodDecl *method,
+ ObjCMethodDecl *prevMethod) {
+ // Merge the objc_requires_super attribute.
+ if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() &&
+ !method->hasAttr<ObjCRequiresSuperAttr>()) {
+ // merge the attribute into implementation.
+ method->addAttr(
+ ObjCRequiresSuperAttr::CreateImplicit(S.Context,
+ method->getLocation()));
+ }
+
+ // Merge nullability of the result type.
+ QualType newReturnType
+ = mergeTypeNullabilityForRedecl(
+ S, method->getReturnTypeSourceRange().getBegin(),
+ method->getReturnType(),
+ method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,
+ prevMethod->getReturnTypeSourceRange().getBegin(),
+ prevMethod->getReturnType(),
+ prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);
+ method->setReturnType(newReturnType);
+
+ // Handle each of the parameters.
+ unsigned numParams = method->param_size();
+ unsigned numPrevParams = prevMethod->param_size();
+ for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) {
+ ParmVarDecl *param = method->param_begin()[i];
+ ParmVarDecl *prevParam = prevMethod->param_begin()[i];
+
+ // Merge nullability.
+ QualType newParamType
+ = mergeTypeNullabilityForRedecl(
+ S, param->getLocation(), param->getType(),
+ param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,
+ prevParam->getLocation(), prevParam->getType(),
+ prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);
+ param->setType(newParamType);
+ }
+}
+
Decl *Sema::ActOnMethodDeclaration(
Scope *S,
SourceLocation MethodLoc, SourceLocation EndLoc,
@@ -3113,7 +4109,9 @@ Decl *Sema::ActOnMethodDeclaration(
if (CheckFunctionReturnType(resultDeclType, MethodLoc))
return nullptr;
- HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());
+ QualType bareResultType = resultDeclType;
+ (void)AttributedType::stripOuterNullability(bareResultType);
+ HasRelatedResultType = (bareResultType == Context.getObjCInstanceType());
} else { // get the type for "id".
resultDeclType = Context.getObjCIdType();
Diag(MethodLoc, diag::warn_missing_method_return_type)
@@ -3214,22 +4212,20 @@ Decl *Sema::ActOnMethodDeclaration(
ImpDecl->addClassMethod(ObjCMethod);
}
- ObjCMethodDecl *IMD = nullptr;
- if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
- IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
- ObjCMethod->isInstanceMethod());
- if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&
- !ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {
- // merge the attribute into implementation.
- ObjCMethod->addAttr(ObjCRequiresSuperAttr::CreateImplicit(Context,
- ObjCMethod->getLocation()));
- }
- if (isa<ObjCCategoryImplDecl>(ImpDecl)) {
- ObjCMethodFamily family =
- ObjCMethod->getSelector().getMethodFamily();
- if (family == OMF_dealloc && IMD && IMD->isOverriding())
- Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)
- << ObjCMethod->getDeclName();
+ // Merge information from the @interface declaration into the
+ // @implementation.
+ if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {
+ if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
+ ObjCMethod->isInstanceMethod())) {
+ mergeInterfaceMethodToImpl(*this, ObjCMethod, IMD);
+
+ // Warn about defining -dealloc in a category.
+ if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() &&
+ ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) {
+ Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)
+ << ObjCMethod->getDeclName();
+ }
+ }
}
} else {
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
@@ -3286,7 +4282,7 @@ Decl *Sema::ActOnMethodDeclaration(
case OMF_alloc:
case OMF_new:
- InferRelatedResultType = ObjCMethod->isClassMethod();
+ InferRelatedResultType = ObjCMethod->isClassMethod();
break;
case OMF_init:
@@ -3297,7 +4293,8 @@ Decl *Sema::ActOnMethodDeclaration(
break;
}
- if (InferRelatedResultType)
+ if (InferRelatedResultType &&
+ !ObjCMethod->getReturnType()->isObjCIndependentClassType())
ObjCMethod->SetRelatedResultType();
}
@@ -3487,12 +4484,11 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
if (ReferencedSelectors.empty() ||
!Context.AnyObjCImplementation())
return;
- for (llvm::DenseMap<Selector, SourceLocation>::iterator S =
- ReferencedSelectors.begin(),
- E = ReferencedSelectors.end(); S != E; ++S) {
- Selector Sel = (*S).first;
+ for (auto &SelectorAndLocation : ReferencedSelectors) {
+ Selector Sel = SelectorAndLocation.first;
+ SourceLocation Loc = SelectorAndLocation.second;
if (!LookupImplementedMethodInGlobalPool(Sel))
- Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
+ Diag(Loc, diag::warn_unimplemented_selector) << Sel;
}
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 2387325..0941870 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -167,13 +167,13 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
void
Sema::UpdateExceptionSpec(FunctionDecl *FD,
const FunctionProtoType::ExceptionSpecInfo &ESI) {
- for (auto *Redecl : FD->redecls())
- Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
-
// If we've fully resolved the exception specification, notify listeners.
if (!isUnresolvedExceptionSpec(ESI.Type))
if (auto *Listener = getASTMutationListener())
Listener->ResolvedExceptionSpec(FD);
+
+ for (auto *Redecl : FD->redecls())
+ Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
/// Determine whether a function has an implicitly-generated exception
@@ -397,7 +397,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// - both are dynamic-exception-specifications that have the same set of
// adjusted types.
//
- // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is
+ // C++0x [except.spec]p12: An exception-specification is non-throwing if it is
// of the form throw(), noexcept, or noexcept(constant-expression) where the
// constant-expression yields true.
//
@@ -437,7 +437,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
OldNR != FunctionProtoType::NR_NoNoexcept &&
NewNR != FunctionProtoType::NR_NoNoexcept) {
Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0)
+ if (NoteID.getDiagID() != 0 && OldLoc.isValid())
Diag(OldLoc, NoteID);
return true;
}
@@ -518,7 +518,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
}
Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0)
+ if (NoteID.getDiagID() != 0 && OldLoc.isValid())
Diag(OldLoc, NoteID);
return true;
}
@@ -547,7 +547,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
return false;
}
Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0)
+ if (NoteID.getDiagID() != 0 && OldLoc.isValid())
Diag(OldLoc, NoteID);
return true;
}
@@ -837,11 +837,13 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
New->getLocation());
}
-static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
- Expr *E = const_cast<Expr*>(CE);
+static CanThrowResult canSubExprsThrow(Sema &S, const Expr *E) {
CanThrowResult R = CT_Cannot;
- for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
- R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
+ for (const Stmt *SubStmt : E->children()) {
+ R = mergeCanThrow(R, S.canThrow(cast<Expr>(SubStmt)));
+ if (R == CT_Can)
+ break;
+ }
return R;
}
@@ -1041,6 +1043,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXStdInitializerListExprClass:
case Expr::DesignatedInitExprClass:
+ case Expr::DesignatedInitUpdateExprClass:
case Expr::ExprWithCleanupsClass:
case Expr::ExtVectorElementExprClass:
case Expr::InitListExprClass:
@@ -1135,6 +1138,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ImaginaryLiteralClass:
case Expr::ImplicitValueInitExprClass:
case Expr::IntegerLiteralClass:
+ case Expr::NoInitExprClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCBoolLiteralExprClass:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index 8be1157..1ae983c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -76,25 +76,57 @@ bool Sema::CanUseDecl(NamedDecl *D) {
static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
// Warn if this is used but marked unused.
if (D->hasAttr<UnusedAttr>()) {
- const Decl *DC = cast<Decl>(S.getCurObjCLexicalContext());
- if (!DC->hasAttr<UnusedAttr>())
+ const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext());
+ if (DC && !DC->hasAttr<UnusedAttr>())
S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
}
}
-static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
- NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- bool ObjCPropertyAccess) {
+static bool HasRedeclarationWithoutAvailabilityInCategory(const Decl *D) {
+ const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
+ if (!OMD)
+ return false;
+ const ObjCInterfaceDecl *OID = OMD->getClassInterface();
+ if (!OID)
+ return false;
+
+ for (const ObjCCategoryDecl *Cat : OID->visible_categories())
+ if (ObjCMethodDecl *CatMeth =
+ Cat->getMethod(OMD->getSelector(), OMD->isInstanceMethod()))
+ if (!CatMeth->hasAttr<AvailabilityAttr>())
+ return true;
+ return false;
+}
+
+static AvailabilityResult
+DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess) {
// See if this declaration is unavailable or deprecated.
std::string Message;
+ AvailabilityResult Result = D->getAvailability(&Message);
+
+ // For typedefs, if the typedef declaration appears available look
+ // to the underlying type to see if it is more restrictive.
+ while (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ if (Result == AR_Available) {
+ if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+ D = TT->getDecl();
+ Result = D->getAvailability(&Message);
+ continue;
+ }
+ }
+ break;
+ }
// Forward class declarations get their attributes from their definition.
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
- if (IDecl->getDefinition())
+ if (IDecl->getDefinition()) {
D = IDecl->getDefinition();
+ Result = D->getAvailability(&Message);
+ }
}
- AvailabilityResult Result = D->getAvailability(&Message);
+
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
if (Result == AR_Available) {
const DeclContext *DC = ECD->getDeclContext();
@@ -103,7 +135,8 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
}
const ObjCPropertyDecl *ObjCPDecl = nullptr;
- if (Result == AR_Deprecated || Result == AR_Unavailable) {
+ if (Result == AR_Deprecated || Result == AR_Unavailable ||
+ AR_NotYetIntroduced) {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
@@ -115,7 +148,6 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
switch (Result) {
case AR_Available:
- case AR_NotYetIntroduced:
break;
case AR_Deprecated:
@@ -125,6 +157,34 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
ObjCPropertyAccess);
break;
+ case AR_NotYetIntroduced: {
+ // Don't do this for enums, they can't be redeclared.
+ if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
+ break;
+
+ bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited();
+ // Objective-C method declarations in categories are not modelled as
+ // redeclarations, so manually look for a redeclaration in a category
+ // if necessary.
+ if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D))
+ Warn = false;
+ // In general, D will point to the most recent redeclaration. However,
+ // for `@class A;` decls, this isn't true -- manually go through the
+ // redecl chain in that case.
+ if (Warn && isa<ObjCInterfaceDecl>(D))
+ for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn;
+ Redecl = Redecl->getPreviousDecl())
+ if (!Redecl->hasAttr<AvailabilityAttr>() ||
+ Redecl->getAttr<AvailabilityAttr>()->isInherited())
+ Warn = false;
+
+ if (Warn)
+ S.EmitAvailabilityWarning(Sema::AD_Partial, D, Message, Loc,
+ UnknownObjCClass, ObjCPDecl,
+ ObjCPropertyAccess);
+ break;
+ }
+
case AR_Unavailable:
if (S.getCurContextAvailability() != AR_Unavailable)
S.EmitAvailabilityWarning(Sema::AD_Unavailable,
@@ -307,7 +367,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
DeduceReturnType(FD, Loc))
return true;
}
- DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess);
+ DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass,
+ ObjCPropertyAccess);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -405,12 +466,11 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
SourceLocation MissingNilLoc
= PP.getLocForEndOfToken(sentinelExpr->getLocEnd());
std::string NullValue;
- if (calleeType == CT_Method &&
- PP.getIdentifierInfo("nil")->hasMacroDefinition())
+ if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
else if (getLangOpts().CPlusPlus11)
NullValue = "nullptr";
- else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition())
+ else if (PP.isMacroDefined("NULL"))
NullValue = "NULL";
else
NullValue = "(void*) 0";
@@ -1050,10 +1110,15 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
return RHSType;
}
- if (LHSFloat)
+ if (LHSFloat) {
+ // Half FP has to be promoted to float unless it is natively supported
+ if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
+ LHSType = S.Context.FloatTy;
+
return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*convertFloat=*/!IsCompAssign,
/*convertInt=*/ true);
+ }
assert(RHSFloat);
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*convertInt=*/ true,
@@ -2401,8 +2466,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context)
- ObjCIvarRefExpr(IV, IV->getType(), Loc, IV->getLocation(),
- SelfExpr.get(), true, true);
+ ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
+ IV->getLocation(), SelfExpr.get(), true, true);
if (getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
@@ -3266,7 +3331,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Ty == Context.DoubleTy) {
if (getLangOpts().SinglePrecisionConstants) {
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
- } else if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp64) {
+ } else if (getLangOpts().OpenCL &&
+ !((getLangOpts().OpenCLVersion >= 120) ||
+ getOpenCLOptions().cl_khr_fp64)) {
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
@@ -3322,6 +3389,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Diag(Tok.getLocation(), diag::err_int128_unsupported);
Width = MaxWidth;
Ty = Context.getIntMaxType();
+ } else if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
+ Width = 8;
+ Ty = Context.CharTy;
} else {
Width = Literal.MicrosoftInteger;
Ty = Context.getIntTypeForBitwidth(Width,
@@ -3355,6 +3425,22 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Ty = Context.LongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongTy;
+ // Check according to the rules of C90 6.1.3.2p5. C++03 [lex.icon]p2
+ // is compatible.
+ else if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) {
+ const unsigned LongLongSize =
+ Context.getTargetInfo().getLongLongWidth();
+ Diag(Tok.getLocation(),
+ getLangOpts().CPlusPlus
+ ? Literal.isLong
+ ? diag::warn_old_implicitly_unsigned_long_cxx
+ : /*C++98 UB*/ diag::
+ ext_old_implicitly_unsigned_long_cxx
+ : diag::warn_old_implicitly_unsigned_long)
+ << (LongLongSize > LongSize ? /*will have type 'long long'*/ 0
+ : /*will be ill-formed*/ 1);
+ Ty = Context.UnsignedLongTy;
+ }
Width = LongSize;
}
}
@@ -3603,7 +3689,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
// C11 6.5.3.4/3, C++11 [expr.alignof]p3:
// When alignof or _Alignof is applied to an array type, the result
// is the alignment of the element type.
- if (ExprKind == UETT_AlignOf)
+ if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign)
ExprType = Context.getBaseElementType(ExprType);
if (ExprKind == UETT_VecStep)
@@ -3738,6 +3824,9 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
isInvalid = CheckAlignOfExpr(*this, E);
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E);
+ } else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
+ Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
+ isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
isInvalid = true;
@@ -4228,7 +4317,6 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
SourceLocation RParenLoc,
bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
- // We don't need to do this in the
if (FDecl)
if (unsigned ID = FDecl->getBuiltinID())
if (Context.BuiltinInfo.hasCustomTypechecking(ID))
@@ -4558,6 +4646,83 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
return hasInvalid;
}
+/// If a builtin function has a pointer argument with no explicit address
+/// space, than it should be able to accept a pointer to any address
+/// space as input. In order to do this, we need to replace the
+/// standard builtin declaration with one that uses the same address space
+/// as the call.
+///
+/// \returns nullptr If this builtin is not a candidate for a rewrite i.e.
+/// it does not contain any pointer arguments without
+/// an address space qualifer. Otherwise the rewritten
+/// FunctionDecl is returned.
+/// TODO: Handle pointer return types.
+static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
+ const FunctionDecl *FDecl,
+ MultiExprArg ArgExprs) {
+
+ QualType DeclType = FDecl->getType();
+ const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(DeclType);
+
+ if (!Context.BuiltinInfo.hasPtrArgsOrResult(FDecl->getBuiltinID()) ||
+ !FT || FT->isVariadic() || ArgExprs.size() != FT->getNumParams())
+ return nullptr;
+
+ bool NeedsNewDecl = false;
+ unsigned i = 0;
+ SmallVector<QualType, 8> OverloadParams;
+
+ for (QualType ParamType : FT->param_types()) {
+
+ // Convert array arguments to pointer to simplify type lookup.
+ Expr *Arg = Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]).get();
+ QualType ArgType = Arg->getType();
+ if (!ParamType->isPointerType() ||
+ ParamType.getQualifiers().hasAddressSpace() ||
+ !ArgType->isPointerType() ||
+ !ArgType->getPointeeType().getQualifiers().hasAddressSpace()) {
+ OverloadParams.push_back(ParamType);
+ continue;
+ }
+
+ NeedsNewDecl = true;
+ unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace();
+
+ QualType PointeeType = ParamType->getPointeeType();
+ PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
+ OverloadParams.push_back(Context.getPointerType(PointeeType));
+ }
+
+ if (!NeedsNewDecl)
+ return nullptr;
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ QualType OverloadTy = Context.getFunctionType(FT->getReturnType(),
+ OverloadParams, EPI);
+ DeclContext *Parent = Context.getTranslationUnitDecl();
+ FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent,
+ FDecl->getLocation(),
+ FDecl->getLocation(),
+ FDecl->getIdentifier(),
+ OverloadTy,
+ /*TInfo=*/nullptr,
+ SC_Extern, false,
+ /*hasPrototype=*/true);
+ SmallVector<ParmVarDecl*, 16> Params;
+ FT = cast<FunctionProtoType>(OverloadTy);
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
+ QualType ParamType = FT->getParamType(i);
+ ParmVarDecl *Parm =
+ ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(),
+ SourceLocation(), nullptr, ParamType,
+ /*TInfo=*/nullptr, SC_None, nullptr);
+ Parm->setScopeInfo(0, i);
+ Params.push_back(Parm);
+ }
+ OverloadDecl->setParams(Params);
+ return OverloadDecl;
+}
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -4661,10 +4826,24 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
if (UnOp->getOpcode() == UO_AddrOf)
NakedFn = UnOp->getSubExpr()->IgnoreParens();
-
- if (isa<DeclRefExpr>(NakedFn))
+
+ if (isa<DeclRefExpr>(NakedFn)) {
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
- else if (isa<MemberExpr>(NakedFn))
+
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
+ if (FDecl && FDecl->getBuiltinID()) {
+ // Rewrite the function decl for this builtin by replacing paramaters
+ // with no explicit address space with the address space of the arguments
+ // in ArgExprs.
+ if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
+ NDecl = FDecl;
+ Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(),
+ SourceLocation(), FDecl, false,
+ SourceLocation(), FDecl->getType(),
+ Fn->getValueKind(), FDecl);
+ }
+ }
+ } else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
@@ -4761,6 +4940,17 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy,
VK_RValue, RParenLoc);
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot always handle TypoExpr nodes in builtin calls and direct
+ // function calls as their argument checking don't necessarily handle
+ // dependent types properly, so make sure any TypoExprs have been
+ // dealt with.
+ ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
+ if (!Result.isUsable()) return ExprError();
+ TheCall = dyn_cast<CallExpr>(Result.get());
+ if (!TheCall) return Result;
+ }
+
// Bail out early if calling a builtin with custom typechecking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
@@ -4995,17 +5185,17 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
}
/// Do an explicit extend of the given block pointer if we're in ARC.
-static void maybeExtendBlockObject(Sema &S, ExprResult &E) {
+void Sema::maybeExtendBlockObject(ExprResult &E) {
assert(E.get()->getType()->isBlockPointerType());
assert(E.get()->isRValue());
// Only do this in an r-value context.
- if (!S.getLangOpts().ObjCAutoRefCount) return;
+ if (!getLangOpts().ObjCAutoRefCount) return;
- E = ImplicitCastExpr::Create(S.Context, E.get()->getType(),
+ E = ImplicitCastExpr::Create(Context, E.get()->getType(),
CK_ARCExtendBlockObject, E.get(),
/*base path*/ nullptr, VK_RValue);
- S.ExprNeedsCleanups = true;
+ ExprNeedsCleanups = true;
}
/// Prepare a conversion of the given expression to an ObjC object
@@ -5015,7 +5205,7 @@ CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) {
if (type->isObjCObjectPointerType()) {
return CK_BitCast;
} else if (type->isBlockPointerType()) {
- maybeExtendBlockObject(*this, E);
+ maybeExtendBlockObject(E);
return CK_BlockPointerToObjCPointerCast;
} else {
assert(type->isPointerType());
@@ -5057,7 +5247,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_BitCast;
if (SrcKind == Type::STK_CPointer)
return CK_CPointerToObjCPointerCast;
- maybeExtendBlockObject(*this, Src);
+ maybeExtendBlockObject(Src);
return CK_BlockPointerToObjCPointerCast;
case Type::STK_Bool:
return CK_PointerToBoolean;
@@ -5516,47 +5706,24 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
}
/// \brief Return false if the condition expression is valid, true otherwise.
-static bool checkCondition(Sema &S, Expr *Cond) {
+static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
QualType CondTy = Cond->getType();
+ // OpenCL v1.1 s6.3.i says the condition cannot be a floating point type.
+ if (S.getLangOpts().OpenCL && CondTy->isFloatingType()) {
+ S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
+ << CondTy << Cond->getSourceRange();
+ return true;
+ }
+
// C99 6.5.15p2
if (CondTy->isScalarType()) return false;
- // OpenCL v1.1 s6.3.i says the condition is allowed to be a vector or scalar.
- if (S.getLangOpts().OpenCL && CondTy->isVectorType())
- return false;
-
- // Emit the proper error message.
- S.Diag(Cond->getLocStart(), S.getLangOpts().OpenCL ?
- diag::err_typecheck_cond_expect_scalar :
- diag::err_typecheck_cond_expect_scalar_or_vector)
- << CondTy;
+ S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_scalar)
+ << CondTy << Cond->getSourceRange();
return true;
}
-/// \brief Return false if the two expressions can be converted to a vector,
-/// true otherwise
-static bool checkConditionalConvertScalarsToVectors(Sema &S, ExprResult &LHS,
- ExprResult &RHS,
- QualType CondTy) {
- // Both operands should be of scalar type.
- if (!LHS.get()->getType()->isScalarType()) {
- S.Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
- << CondTy;
- return true;
- }
- if (!RHS.get()->getType()->isScalarType()) {
- S.Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
- << CondTy;
- return true;
- }
-
- // Implicity convert these scalars to the type of the condition.
- LHS = S.ImpCastExprToType(LHS.get(), CondTy, CK_IntegralCast);
- RHS = S.ImpCastExprToType(RHS.get(), CondTy, CK_IntegralCast);
- return false;
-}
-
/// \brief Handle when one or both operands are void type.
static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
ExprResult &RHS) {
@@ -5659,36 +5826,6 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
return ResultTy;
}
-/// \brief Returns true if QT is quelified-id and implements 'NSObject' and/or
-/// 'NSCopying' protocols (and nothing else); or QT is an NSObject and optionally
-/// implements 'NSObject' and/or NSCopying' protocols (and nothing else).
-static bool isObjCPtrBlockCompatible(Sema &S, ASTContext &C, QualType QT) {
- if (QT->isObjCIdType())
- return true;
-
- const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
- if (!OPT)
- return false;
-
- if (ObjCInterfaceDecl *ID = OPT->getInterfaceDecl())
- if (ID->getIdentifier() != &C.Idents.get("NSObject"))
- return false;
-
- ObjCProtocolDecl* PNSCopying =
- S.LookupProtocol(&C.Idents.get("NSCopying"), SourceLocation());
- ObjCProtocolDecl* PNSObject =
- S.LookupProtocol(&C.Idents.get("NSObject"), SourceLocation());
-
- for (auto *Proto : OPT->quals()) {
- if ((PNSCopying && declaresSameEntity(Proto, PNSCopying)) ||
- (PNSObject && declaresSameEntity(Proto, PNSObject)))
- ;
- else
- return false;
- }
- return true;
-}
-
/// \brief Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
@@ -5773,6 +5910,184 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
return true;
}
+/// \brief Simple conversion between integer and floating point types.
+///
+/// Used when handling the OpenCL conditional operator where the
+/// condition is a vector while the other operands are scalar.
+///
+/// OpenCL v1.1 s6.3.i and s6.11.6 together require that the scalar
+/// types are either integer or floating type. Between the two
+/// operands, the type with the higher rank is defined as the "result
+/// type". The other operand needs to be promoted to the same type. No
+/// other type promotion is allowed. We cannot use
+/// UsualArithmeticConversions() for this purpose, since it always
+/// promotes promotable types.
+static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation QuestionLoc) {
+ LHS = S.DefaultFunctionArrayLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
+
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType LHSType =
+ S.Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
+ QualType RHSType =
+ S.Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+
+ if (!LHSType->isIntegerType() && !LHSType->isRealFloatingType()) {
+ S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
+ << LHSType << LHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ if (!RHSType->isIntegerType() && !RHSType->isRealFloatingType()) {
+ S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
+ << RHSType << RHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ // If both types are identical, no conversion is needed.
+ if (LHSType == RHSType)
+ return LHSType;
+
+ // Now handle "real" floating types (i.e. float, double, long double).
+ if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType())
+ return handleFloatConversion(S, LHS, RHS, LHSType, RHSType,
+ /*IsCompAssign = */ false);
+
+ // Finally, we have two differing integer types.
+ return handleIntegerConversion<doIntegralCast, doIntegralCast>
+ (S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
+}
+
+/// \brief Convert scalar operands to a vector that matches the
+/// condition in length.
+///
+/// Used when handling the OpenCL conditional operator where the
+/// condition is a vector while the other operands are scalar.
+///
+/// We first compute the "result type" for the scalar operands
+/// according to OpenCL v1.1 s6.3.i. Both operands are then converted
+/// into a vector of that type where the length matches the condition
+/// vector type. s6.11.6 requires that the element types of the result
+/// and the condition must have the same number of bits.
+static QualType
+OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS,
+ QualType CondTy, SourceLocation QuestionLoc) {
+ QualType ResTy = OpenCLArithmeticConversions(S, LHS, RHS, QuestionLoc);
+ if (ResTy.isNull()) return QualType();
+
+ const VectorType *CV = CondTy->getAs<VectorType>();
+ assert(CV);
+
+ // Determine the vector result type
+ unsigned NumElements = CV->getNumElements();
+ QualType VectorTy = S.Context.getExtVectorType(ResTy, NumElements);
+
+ // Ensure that all types have the same number of bits
+ if (S.Context.getTypeSize(CV->getElementType())
+ != S.Context.getTypeSize(ResTy)) {
+ // Since VectorTy is created internally, it does not pretty print
+ // with an OpenCL name. Instead, we just print a description.
+ std::string EleTyName = ResTy.getUnqualifiedType().getAsString();
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "(vector of " << NumElements << " '" << EleTyName << "' values)";
+ S.Diag(QuestionLoc, diag::err_conditional_vector_element_size)
+ << CondTy << OS.str();
+ return QualType();
+ }
+
+ // Convert operands to the vector result type
+ LHS = S.ImpCastExprToType(LHS.get(), VectorTy, CK_VectorSplat);
+ RHS = S.ImpCastExprToType(RHS.get(), VectorTy, CK_VectorSplat);
+
+ return VectorTy;
+}
+
+/// \brief Return false if this is a valid OpenCL condition vector
+static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
+ SourceLocation QuestionLoc) {
+ // OpenCL v1.1 s6.11.6 says the elements of the vector must be of
+ // integral type.
+ const VectorType *CondTy = Cond->getType()->getAs<VectorType>();
+ assert(CondTy);
+ QualType EleTy = CondTy->getElementType();
+ if (EleTy->isIntegerType()) return false;
+
+ S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
+ << Cond->getType() << Cond->getSourceRange();
+ return true;
+}
+
+/// \brief Return false if the vector condition type and the vector
+/// result type are compatible.
+///
+/// OpenCL v1.1 s6.11.6 requires that both vector types have the same
+/// number of elements, and their element types have the same number
+/// of bits.
+static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
+ SourceLocation QuestionLoc) {
+ const VectorType *CV = CondTy->getAs<VectorType>();
+ const VectorType *RV = VecResTy->getAs<VectorType>();
+ assert(CV && RV);
+
+ if (CV->getNumElements() != RV->getNumElements()) {
+ S.Diag(QuestionLoc, diag::err_conditional_vector_size)
+ << CondTy << VecResTy;
+ return true;
+ }
+
+ QualType CVE = CV->getElementType();
+ QualType RVE = RV->getElementType();
+
+ if (S.Context.getTypeSize(CVE) != S.Context.getTypeSize(RVE)) {
+ S.Diag(QuestionLoc, diag::err_conditional_vector_element_size)
+ << CondTy << VecResTy;
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Return the resulting type for the conditional operator in
+/// OpenCL (aka "ternary selection operator", OpenCL v1.1
+/// s6.3.i) when the condition is a vector type.
+static QualType
+OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
+ ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc) {
+ Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get());
+ if (Cond.isInvalid())
+ return QualType();
+ QualType CondTy = Cond.get()->getType();
+
+ if (checkOpenCLConditionVector(S, Cond.get(), QuestionLoc))
+ return QualType();
+
+ // If either operand is a vector then find the vector type of the
+ // result as specified in OpenCL v1.1 s6.3.i.
+ if (LHS.get()->getType()->isVectorType() ||
+ RHS.get()->getType()->isVectorType()) {
+ QualType VecResTy = S.CheckVectorOperands(LHS, RHS, QuestionLoc,
+ /*isCompAssign*/false);
+ if (VecResTy.isNull()) return QualType();
+ // The result type must match the condition type as specified in
+ // OpenCL v1.1 s6.11.6.
+ if (checkVectorResult(S, CondTy, VecResTy, QuestionLoc))
+ return QualType();
+ return VecResTy;
+ }
+
+ // Both operands are scalar.
+ return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
+}
+
/// Note that LHS is not null here, even if this is the gnu "x ?: y" extension.
/// In that case, LHS = cond.
/// C99 6.5.15
@@ -5796,11 +6111,16 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
VK = VK_RValue;
OK = OK_Ordinary;
+ // The OpenCL operator with a vector condition is sufficiently
+ // different to merit its own checker.
+ if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType())
+ return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc);
+
// First, check the condition.
Cond = UsualUnaryConversions(Cond.get());
if (Cond.isInvalid())
return QualType();
- if (checkCondition(*this, Cond.get()))
+ if (checkCondition(*this, Cond.get(), QuestionLoc))
return QualType();
// Now check the two expressions.
@@ -5812,17 +6132,9 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- QualType CondTy = Cond.get()->getType();
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
- // If the condition is a vector, and both operands are scalar,
- // attempt to implicity convert them to the vector type to act like the
- // built in select. (OpenCL v1.1 s6.3.i)
- if (getLangOpts().OpenCL && CondTy->isVectorType())
- if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy))
- return QualType();
-
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
@@ -5961,7 +6273,10 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
// FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
// It could return the composite type.
- if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
+ if (!(compositeType =
+ Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) {
+ // Nothing more to do.
+ } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
} else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
@@ -5975,10 +6290,7 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
compositeType = Context.getObjCIdType();
} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
- } else if (!(compositeType =
- Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
- ;
- else {
+ } else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
@@ -6116,6 +6428,8 @@ static bool ExprLooksBoolean(Expr *E) {
return IsLogicOp(OP->getOpcode());
if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E))
return OP->getOpcode() == UO_LNot;
+ if (E->getType()->isPointerType())
+ return true;
return false;
}
@@ -6218,6 +6532,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(),
RHS.get());
+ CheckBoolLikeConversion(Cond.get(), QuestionLoc);
+
if (!commonExpr)
return new (Context)
ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc,
@@ -6662,9 +6978,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
// Only under strict condition T^ is compatible with an Objective-C pointer.
- if (RHSType->isBlockPointerType() &&
- isObjCPtrBlockCompatible(*this, Context, LHSType)) {
- maybeExtendBlockObject(*this, RHS);
+ if (RHSType->isBlockPointerType() &&
+ LHSType->isBlockCompatibleObjCPointerType(Context)) {
+ maybeExtendBlockObject(RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
}
@@ -7178,9 +7494,12 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
/// \returns True if pointer has incomplete type
static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
Expr *Operand) {
- assert(Operand->getType()->isAnyPointerType() &&
- !Operand->getType()->isDependentType());
- QualType PointeeTy = Operand->getType()->getPointeeType();
+ QualType ResType = Operand->getType();
+ if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
+ ResType = ResAtomicType->getValueType();
+
+ assert(ResType->isAnyPointerType() && !ResType->isDependentType());
+ QualType PointeeTy = ResType->getPointeeType();
return S.RequireCompleteType(Loc, PointeeTy,
diag::err_typecheck_arithmetic_incomplete_type,
PointeeTy, Operand->getSourceRange());
@@ -7196,9 +7515,13 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
/// \returns True when the operand is valid to use (even if as an extension).
static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
Expr *Operand) {
- if (!Operand->getType()->isAnyPointerType()) return true;
+ QualType ResType = Operand->getType();
+ if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
+ ResType = ResAtomicType->getValueType();
- QualType PointeeTy = Operand->getType()->getPointeeType();
+ if (!ResType->isAnyPointerType()) return true;
+
+ QualType PointeeTy = ResType->getPointeeType();
if (PointeeTy->isVoidType()) {
diagnoseArithmeticOnVoidPointer(S, Loc, Operand);
return !S.getLangOpts().CPlusPlus;
@@ -7558,7 +7881,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
llvm::APSInt Right;
// Check right/shifter operand
if (RHS.get()->isValueDependent() ||
- !RHS.get()->isIntegerConstantExpr(Right, S.Context))
+ !RHS.get()->EvaluateAsInt(Right, S.Context))
return;
if (Right.isNegative()) {
@@ -7584,9 +7907,19 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// representable in the result type, so never warn for those.
llvm::APSInt Left;
if (LHS.get()->isValueDependent() ||
- !LHS.get()->isIntegerConstantExpr(Left, S.Context) ||
- LHSType->hasUnsignedIntegerRepresentation())
+ LHSType->hasUnsignedIntegerRepresentation() ||
+ !LHS.get()->EvaluateAsInt(Left, S.Context))
+ return;
+
+ // If LHS does not have a signed type and non-negative value
+ // then, the behavior is undefined. Warn about it.
+ if (Left.isNegative()) {
+ S.DiagRuntimeBehavior(Loc, LHS.get(),
+ S.PDiag(diag::warn_shift_lhs_negative)
+ << LHS.get()->getSourceRange());
return;
+ }
+
llvm::APInt ResultBits =
static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
if (LeftBits.uge(ResultBits))
@@ -7605,7 +7938,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// turned off separately if needed.
if (LeftBits == ResultBits - 1) {
S.Diag(Loc, diag::warn_shift_result_sets_sign_bit)
- << HexResult.str() << LHSType
+ << HexResult << LHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return;
}
@@ -7616,6 +7949,69 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
+/// \brief Return the resulting type when an OpenCL vector is shifted
+/// by a scalar or vector shift amount.
+static QualType checkOpenCLVectorShift(Sema &S,
+ ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool IsCompAssign) {
+ // OpenCL v1.1 s6.3.j says RHS can be a vector only if LHS is a vector.
+ if (!LHS.get()->getType()->isVectorType()) {
+ S.Diag(Loc, diag::err_shift_rhs_only_vector)
+ << RHS.get()->getType() << LHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ if (!IsCompAssign) {
+ LHS = S.UsualUnaryConversions(LHS.get());
+ if (LHS.isInvalid()) return QualType();
+ }
+
+ RHS = S.UsualUnaryConversions(RHS.get());
+ if (RHS.isInvalid()) return QualType();
+
+ QualType LHSType = LHS.get()->getType();
+ const VectorType *LHSVecTy = LHSType->getAs<VectorType>();
+ QualType LHSEleType = LHSVecTy->getElementType();
+
+ // Note that RHS might not be a vector.
+ QualType RHSType = RHS.get()->getType();
+ const VectorType *RHSVecTy = RHSType->getAs<VectorType>();
+ QualType RHSEleType = RHSVecTy ? RHSVecTy->getElementType() : RHSType;
+
+ // OpenCL v1.1 s6.3.j says that the operands need to be integers.
+ if (!LHSEleType->isIntegerType()) {
+ S.Diag(Loc, diag::err_typecheck_expect_int)
+ << LHS.get()->getType() << LHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ if (!RHSEleType->isIntegerType()) {
+ S.Diag(Loc, diag::err_typecheck_expect_int)
+ << RHS.get()->getType() << RHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ if (RHSVecTy) {
+ // OpenCL v1.1 s6.3.j says that for vector types, the operators
+ // are applied component-wise. So if RHS is a vector, then ensure
+ // that the number of elements is the same as LHS...
+ if (RHSVecTy->getNumElements() != LHSVecTy->getNumElements()) {
+ S.Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ return QualType();
+ }
+ } else {
+ // ...else expand RHS to match the number of elements in LHS.
+ QualType VecTy =
+ S.Context.getExtVectorType(RHSEleType, LHSVecTy->getNumElements());
+ RHS = S.ImpCastExprToType(RHS.get(), VecTy, CK_VectorSplat);
+ }
+
+ return LHSType;
+}
+
// C99 6.5.7
QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, unsigned Opc,
@@ -7624,8 +8020,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
// Vector shifts promote their scalar inputs to vector type.
if (LHS.get()->getType()->isVectorType() ||
- RHS.get()->getType()->isVectorType())
+ RHS.get()->getType()->isVectorType()) {
+ if (LangOpts.OpenCL)
+ return checkOpenCLVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign);
+ }
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
@@ -7790,9 +8189,6 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
// Get the LHS object's interface type.
QualType InterfaceType = Type->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- InterfaceType->getAsObjCQualifiedInterfaceType())
- InterfaceType = iQFaceTy->getBaseType();
// If the RHS isn't an Objective-C object, bail out.
if (!RHS->getType()->isObjCObjectPointerType())
@@ -7807,8 +8203,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
if (Type->isObjCIdType()) {
// For 'id', just check the global pool.
Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(),
- /*receiverId=*/true,
- /*warn=*/false);
+ /*receiverId=*/true);
} else {
// Check protocols.
Method = S.LookupMethodInQualifiedType(IsEqualSel, Type,
@@ -8614,6 +9009,139 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
+static bool IsTypeModifiable(QualType Ty, bool IsDereference) {
+ Ty = Ty.getNonReferenceType();
+ if (IsDereference && Ty->isPointerType())
+ Ty = Ty->getPointeeType();
+ return !Ty.isConstQualified();
+}
+
+/// Emit the "read-only variable not assignable" error and print notes to give
+/// more information about why the variable is not assignable, such as pointing
+/// to the declaration of a const variable, showing that a method is const, or
+/// that the function is returning a const reference.
+static void DiagnoseConstAssignment(Sema &S, const Expr *E,
+ SourceLocation Loc) {
+ // Update err_typecheck_assign_const and note_typecheck_assign_const
+ // when this enum is changed.
+ enum {
+ ConstFunction,
+ ConstVariable,
+ ConstMember,
+ ConstMethod,
+ ConstUnknown, // Keep as last element
+ };
+
+ SourceRange ExprRange = E->getSourceRange();
+
+ // Only emit one error on the first const found. All other consts will emit
+ // a note to the error.
+ bool DiagnosticEmitted = false;
+
+ // Track if the current expression is the result of a derefence, and if the
+ // next checked expression is the result of a derefence.
+ bool IsDereference = false;
+ bool NextIsDereference = false;
+
+ // Loop to process MemberExpr chains.
+ while (true) {
+ IsDereference = NextIsDereference;
+ NextIsDereference = false;
+
+ E = E->IgnoreParenImpCasts();
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ NextIsDereference = ME->isArrow();
+ const ValueDecl *VD = ME->getMemberDecl();
+ if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
+ // Mutable fields can be modified even if the class is const.
+ if (Field->isMutable()) {
+ assert(DiagnosticEmitted && "Expected diagnostic not emitted.");
+ break;
+ }
+
+ if (!IsTypeModifiable(Field->getType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstMember << false /*static*/ << Field
+ << Field->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMember << false /*static*/ << Field << Field->getType()
+ << Field->getSourceRange();
+ }
+ E = ME->getBase();
+ continue;
+ } else if (const VarDecl *VDecl = dyn_cast<VarDecl>(VD)) {
+ if (VDecl->getType().isConstQualified()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstMember << true /*static*/ << VDecl
+ << VDecl->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMember << true /*static*/ << VDecl << VDecl->getType()
+ << VDecl->getSourceRange();
+ }
+ // Static fields do not inherit constness from parents.
+ break;
+ }
+ break;
+ } // End MemberExpr
+ break;
+ }
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ // Function calls
+ const FunctionDecl *FD = CE->getDirectCallee();
+ if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
+ << ConstFunction << FD;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(FD->getReturnTypeSourceRange().getBegin(),
+ diag::note_typecheck_assign_const)
+ << ConstFunction << FD << FD->getReturnType()
+ << FD->getReturnTypeSourceRange();
+ }
+ } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ // Point to variable declaration.
+ if (const ValueDecl *VD = DRE->getDecl()) {
+ if (!IsTypeModifiable(VD->getType(), IsDereference)) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << ExprRange << ConstVariable << VD << VD->getType();
+ DiagnosticEmitted = true;
+ }
+ S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstVariable << VD << VD->getType() << VD->getSourceRange();
+ }
+ }
+ } else if (isa<CXXThisExpr>(E)) {
+ if (const DeclContext *DC = S.getFunctionLevelDeclContext()) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
+ if (MD->isConst()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
+ << ConstMethod << MD;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(MD->getLocation(), diag::note_typecheck_assign_const)
+ << ConstMethod << MD << MD->getSourceRange();
+ }
+ }
+ }
+ }
+
+ if (DiagnosticEmitted)
+ return;
+
+ // Can't determine a more specific message, so display the generic error.
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown;
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -8630,8 +9158,6 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
bool NeedType = false;
switch (IsLV) { // C99 6.5.16p2
case Expr::MLV_ConstQualified:
- DiagID = diag::err_typecheck_assign_const;
-
// Use a specialized diagnostic when we're assigning to an object
// from an enclosing function or block.
if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
@@ -8670,14 +9196,24 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
- // We need to preserve the AST regardless, so migration tool
+ // We need to preserve the AST regardless, so migration tool
// can do its job.
return false;
}
}
}
+ // If none of the special cases above are triggered, then this is a
+ // simple const assignment.
+ if (DiagID == 0) {
+ DiagnoseConstAssignment(S, E, Loc);
+ return true;
+ }
+
break;
+ case Expr::MLV_ConstAddrSpace:
+ DiagnoseConstAssignment(S, E, Loc);
+ return true;
case Expr::MLV_ArrayType:
case Expr::MLV_ArrayTemporary:
DiagID = diag::err_typecheck_array_not_modifiable_lvalue;
@@ -9189,6 +9725,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
!getLangOpts().CPlusPlus) {
AddressOfError = AO_Register_Variable;
}
+ } else if (isa<MSPropertyDecl>(dcl)) {
+ AddressOfError = AO_Property_Expansion;
} else if (isa<FunctionTemplateDecl>(dcl)) {
return Context.OverloadTy;
} else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
@@ -11443,12 +11981,9 @@ void
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
Decl *LambdaContextDecl,
bool IsDecltype) {
- ExprEvalContexts.push_back(
- ExpressionEvaluationContextRecord(NewContext,
- ExprCleanupObjects.size(),
- ExprNeedsCleanups,
- LambdaContextDecl,
- IsDecltype));
+ ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(),
+ ExprNeedsCleanups, LambdaContextDecl,
+ IsDecltype);
ExprNeedsCleanups = false;
if (!MaybeODRUseExprs.empty())
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
@@ -11580,7 +12115,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
// We (incorrectly) mark overload resolution as an unevaluated context, so we
// can just check that here. Skip the rest of this function if we've already
// marked the function as used.
- if (Func->isUsed(false) || !IsPotentiallyEvaluatedContext(*this)) {
+ if (Func->isUsed(/*CheckUsedAttr=*/false) ||
+ !IsPotentiallyEvaluatedContext(*this)) {
// C++11 [temp.inst]p3:
// Unless a function template specialization has been explicitly
// instantiated or explicitly specialized, the function template
@@ -11635,7 +12171,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
return;
DefineImplicitDestructor(Loc, Destructor);
}
- if (Destructor->isVirtual())
+ if (Destructor->isVirtual() && getLangOpts().AppleKext)
MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
if (MethodDecl->isOverloadedOperator() &&
@@ -11655,7 +12191,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion);
else
DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion);
- } else if (MethodDecl->isVirtual())
+ } else if (MethodDecl->isVirtual() && getLangOpts().AppleKext)
MarkVTableUsed(Loc, MethodDecl->getParent());
}
@@ -11727,7 +12263,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
if (mightHaveNonExternalLinkage(Func))
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
else if (Func->getMostRecentDecl()->isInlined() &&
- (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+ !LangOpts.GNUInline &&
!Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
}
@@ -11997,6 +12533,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
// By default, capture variables by reference.
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
+ if (S.getLangOpts().OpenMP && S.IsOpenMPCapturedVar(Var))
+ DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
@@ -12029,13 +12567,11 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
}
/// \brief Create a field within the lambda class for the variable
-/// being captured. Handle Array captures.
-static ExprResult addAsFieldToClosureType(Sema &S,
- LambdaScopeInfo *LSI,
- VarDecl *Var, QualType FieldType,
- QualType DeclRefType,
- SourceLocation Loc,
- bool RefersToCapturedVariable) {
+/// being captured.
+static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, VarDecl *Var,
+ QualType FieldType, QualType DeclRefType,
+ SourceLocation Loc,
+ bool RefersToCapturedVariable) {
CXXRecordDecl *Lambda = LSI->Lambda;
// Build the non-static data member.
@@ -12046,111 +12582,8 @@ static ExprResult addAsFieldToClosureType(Sema &S,
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
-
- // C++11 [expr.prim.lambda]p21:
- // When the lambda-expression is evaluated, the entities that
- // are captured by copy are used to direct-initialize each
- // corresponding non-static data member of the resulting closure
- // object. (For array members, the array elements are
- // direct-initialized in increasing subscript order.) These
- // initializations are performed in the (unspecified) order in
- // which the non-static data members are declared.
-
- // Introduce a new evaluation context for the initialization, so
- // that temporaries introduced as part of the capture are retained
- // to be re-"exported" from the lambda expression itself.
- EnterExpressionEvaluationContext scope(S, Sema::PotentiallyEvaluated);
-
- // C++ [expr.prim.labda]p12:
- // An entity captured by a lambda-expression is odr-used (3.2) in
- // the scope containing the lambda-expression.
- Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
- DeclRefType, VK_LValue, Loc);
- Var->setReferenced(true);
- Var->markUsed(S.Context);
-
- // When the field has array type, create index variables for each
- // dimension of the array. We use these index variables to subscript
- // the source array, and other clients (e.g., CodeGen) will perform
- // the necessary iteration with these index variables.
- SmallVector<VarDecl *, 4> IndexVariables;
- QualType BaseType = FieldType;
- QualType SizeType = S.Context.getSizeType();
- LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
- while (const ConstantArrayType *Array
- = S.Context.getAsConstantArrayType(BaseType)) {
- // Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = nullptr;
- {
- SmallString<8> Str;
- llvm::raw_svector_ostream OS(Str);
- OS << "__i" << IndexVariables.size();
- IterationVarName = &S.Context.Idents.get(OS.str());
- }
- VarDecl *IterationVar
- = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
- IterationVarName, SizeType,
- S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
- IndexVariables.push_back(IterationVar);
- LSI->ArrayIndexVars.push_back(IterationVar);
-
- // Create a reference to the iteration variable.
- ExprResult IterationVarRef
- = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
- assert(!IterationVarRef.isInvalid() &&
- "Reference to invented variable cannot fail!");
- IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get());
- assert(!IterationVarRef.isInvalid() &&
- "Conversion of invented variable cannot fail!");
-
- // Subscript the array with this iteration variable.
- ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr(
- Ref, Loc, IterationVarRef.get(), Loc);
- if (Subscript.isInvalid()) {
- S.CleanupVarDeclMarking();
- S.DiscardCleanupsInEvaluationContext();
- return ExprError();
- }
-
- Ref = Subscript.get();
- BaseType = Array->getElementType();
- }
-
- // Construct the entity that we will be initializing. For an array, this
- // will be first element in the array, which may require several levels
- // of array-subscript entities.
- SmallVector<InitializedEntity, 4> Entities;
- Entities.reserve(1 + IndexVariables.size());
- Entities.push_back(
- InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(),
- Field->getType(), Loc));
- for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
- Entities.push_back(InitializedEntity::InitializeElement(S.Context,
- 0,
- Entities.back()));
-
- InitializationKind InitKind
- = InitializationKind::CreateDirect(Loc, Loc, Loc);
- InitializationSequence Init(S, Entities.back(), InitKind, Ref);
- ExprResult Result(true);
- if (!Init.Diagnose(S, Entities.back(), InitKind, Ref))
- Result = Init.Perform(S, Entities.back(), InitKind, Ref);
-
- // If this initialization requires any cleanups (e.g., due to a
- // default argument to a copy constructor), note that for the
- // lambda.
- if (S.ExprNeedsCleanups)
- LSI->ExprNeedsCleanups = true;
-
- // Exit the expression evaluation context used for the capture.
- S.CleanupVarDeclMarking();
- S.DiscardCleanupsInEvaluationContext();
- return Result;
}
-
-
/// \brief Capture the given variable in the lambda.
static bool captureInLambda(LambdaScopeInfo *LSI,
VarDecl *Var,
@@ -12228,14 +12661,9 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
}
// Capture this variable in the lambda.
- Expr *CopyExpr = nullptr;
- if (BuildAndDiagnose) {
- ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
- CaptureType, DeclRefType, Loc,
- RefersToCapturedVariable);
- if (!Result.isInvalid())
- CopyExpr = Result.get();
- }
+ if (BuildAndDiagnose)
+ addAsFieldToClosureType(S, LSI, Var, CaptureType, DeclRefType, Loc,
+ RefersToCapturedVariable);
// Compute the type of a reference to this captured variable.
if (ByRef)
@@ -12254,18 +12682,20 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
// Add the capture.
if (BuildAndDiagnose)
LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
- Loc, EllipsisLoc, CaptureType, CopyExpr);
+ Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr);
return true;
}
-bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
- TryCaptureKind Kind, SourceLocation EllipsisLoc,
- bool BuildAndDiagnose,
- QualType &CaptureType,
- QualType &DeclRefType,
- const unsigned *const FunctionScopeIndexToStopAt) {
- bool Nested = Var->isInitCapture();
+bool Sema::tryCaptureVariable(
+ VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
+ SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
+ QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) {
+ // An init-capture is notionally from the context surrounding its
+ // declaration, but its parent DC is the lambda class.
+ DeclContext *VarDC = Var->getDeclContext();
+ if (Var->isInitCapture())
+ VarDC = VarDC->getParent();
DeclContext *DC = CurContext;
const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
@@ -12281,9 +12711,9 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
}
- // If the variable is declared in the current context (and is not an
- // init-capture), there is no need to capture it.
- if (!Nested && Var->getDeclContext() == DC) return true;
+ // If the variable is declared in the current context, there is no need to
+ // capture it.
+ if (VarDC == DC) return true;
// Capture global variables if it is required to use private copy of this
// variable.
@@ -12301,8 +12731,10 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
// the variable.
CaptureType = Var->getType();
DeclRefType = CaptureType.getNonReferenceType();
+ bool Nested = false;
bool Explicit = (Kind != TryCapture_Implicit);
unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
+ unsigned OpenMPLevel = 0;
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
@@ -12329,6 +12761,21 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType))
break;
+ if (getLangOpts().OpenMP) {
+ if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ // OpenMP private variables should not be captured in outer scope, so
+ // just break here.
+ if (RSI->CapRegionKind == CR_OpenMP) {
+ if (isOpenMPPrivateVar(Var, OpenMPLevel)) {
+ Nested = true;
+ DeclRefType = DeclRefType.getUnqualifiedType();
+ CaptureType = Context.getLValueReferenceType(DeclRefType);
+ break;
+ }
+ ++OpenMPLevel;
+ }
+ }
+ }
// If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
@@ -12501,7 +12948,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
FunctionScopesIndex--;
DC = ParentDC;
Explicit = false;
- } while (!Var->getDeclContext()->Equals(DC));
+ } while (!VarDC->Equals(DC));
// Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
// computing the type of the capture at each step, checking type-specific
@@ -13740,7 +14187,17 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
// Bound member functions.
case BuiltinType::BoundMember: {
ExprResult result = E;
- tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function),
+ const Expr *BME = E->IgnoreParens();
+ PartialDiagnostic PD = PDiag(diag::err_bound_member_function);
+ // Try to give a nicer diagnostic if it is a bound member that we recognize.
+ if (isa<CXXPseudoDestructorExpr>(BME)) {
+ PD = PDiag(diag::err_dtor_expr_without_call) << /*pseudo-destructor*/ 1;
+ } else if (const auto *ME = dyn_cast<MemberExpr>(BME)) {
+ if (ME->getMemberNameInfo().getName().getNameKind() ==
+ DeclarationName::CXXDestructorName)
+ PD = PDiag(diag::err_dtor_expr_without_call) << /*destructor*/ 0;
+ }
+ tryToRecoverWithCall(result, PD,
/*complain*/ true);
return result;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index a92b7ac..6608d7c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -20,7 +20,6 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/RecursiveASTVisitor.h"
@@ -113,6 +112,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
bool isDependent = false;
bool LookInScope = false;
+ if (SS.isInvalid())
+ return ParsedType();
+
// If we have an object type, it's because we are in a
// pseudo-destructor-expression or a member access expression, and
// we know what type we're looking for.
@@ -644,37 +646,98 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
if (Ex && !Ex->isTypeDependent()) {
- ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope);
- if (ExRes.isInvalid())
+ QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
+ if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
return ExprError();
- Ex = ExRes.get();
+
+ // Initialize the exception result. This implicitly weeds out
+ // abstract types or types with inaccessible copy constructors.
+
+ // C++0x [class.copymove]p31:
+ // When certain criteria are met, an implementation is allowed to omit the
+ // copy/move construction of a class object [...]
+ //
+ // - in a throw-expression, when the operand is the name of a
+ // non-volatile automatic object (other than a function or
+ // catch-clause
+ // parameter) whose scope does not extend beyond the end of the
+ // innermost enclosing try-block (if there is one), the copy/move
+ // operation from the operand to the exception object (15.1) can be
+ // omitted by constructing the automatic object directly into the
+ // exception object
+ const VarDecl *NRVOVariable = nullptr;
+ if (IsThrownVarInScope)
+ NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false);
+
+ InitializedEntity Entity = InitializedEntity::InitializeException(
+ OpLoc, ExceptionObjectTy,
+ /*NRVO=*/NRVOVariable != nullptr);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope);
+ if (Res.isInvalid())
+ return ExprError();
+ Ex = Res.get();
}
-
+
return new (Context)
CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
}
-/// CheckCXXThrowOperand - Validate the operand of a throw.
-ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
- bool IsThrownVarInScope) {
- // C++ [except.throw]p3:
- // A throw-expression initializes a temporary object, called the exception
- // object, the type of which is determined by removing any top-level
- // cv-qualifiers from the static type of the operand of throw and adjusting
- // the type from "array of T" or "function returning T" to "pointer to T"
- // or "pointer to function returning T", [...]
- if (E->getType().hasQualifiers())
- E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
- E->getValueKind()).get();
-
- ExprResult Res = DefaultFunctionArrayConversion(E);
- if (Res.isInvalid())
- return ExprError();
- E = Res.get();
+static void
+collectPublicBases(CXXRecordDecl *RD,
+ llvm::DenseMap<CXXRecordDecl *, unsigned> &SubobjectsSeen,
+ llvm::SmallPtrSetImpl<CXXRecordDecl *> &VBases,
+ llvm::SetVector<CXXRecordDecl *> &PublicSubobjectsSeen,
+ bool ParentIsPublic) {
+ for (const CXXBaseSpecifier &BS : RD->bases()) {
+ CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl();
+ bool NewSubobject;
+ // Virtual bases constitute the same subobject. Non-virtual bases are
+ // always distinct subobjects.
+ if (BS.isVirtual())
+ NewSubobject = VBases.insert(BaseDecl).second;
+ else
+ NewSubobject = true;
+
+ if (NewSubobject)
+ ++SubobjectsSeen[BaseDecl];
+
+ // Only add subobjects which have public access throughout the entire chain.
+ bool PublicPath = ParentIsPublic && BS.getAccessSpecifier() == AS_public;
+ if (PublicPath)
+ PublicSubobjectsSeen.insert(BaseDecl);
+
+ // Recurse on to each base subobject.
+ collectPublicBases(BaseDecl, SubobjectsSeen, VBases, PublicSubobjectsSeen,
+ PublicPath);
+ }
+}
+
+static void getUnambiguousPublicSubobjects(
+ CXXRecordDecl *RD, llvm::SmallVectorImpl<CXXRecordDecl *> &Objects) {
+ llvm::DenseMap<CXXRecordDecl *, unsigned> SubobjectsSeen;
+ llvm::SmallSet<CXXRecordDecl *, 2> VBases;
+ llvm::SetVector<CXXRecordDecl *> PublicSubobjectsSeen;
+ SubobjectsSeen[RD] = 1;
+ PublicSubobjectsSeen.insert(RD);
+ collectPublicBases(RD, SubobjectsSeen, VBases, PublicSubobjectsSeen,
+ /*ParentIsPublic=*/true);
+
+ for (CXXRecordDecl *PublicSubobject : PublicSubobjectsSeen) {
+ // Skip ambiguous objects.
+ if (SubobjectsSeen[PublicSubobject] > 1)
+ continue;
+ Objects.push_back(PublicSubobject);
+ }
+}
+
+/// CheckCXXThrowOperand - Validate the operand of a throw.
+bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
+ QualType ExceptionObjectTy, Expr *E) {
// If the type of the exception would be an incomplete type or a pointer
// to an incomplete type other than (cv) void the program is ill-formed.
- QualType Ty = E->getType();
+ QualType Ty = ExceptionObjectTy;
bool isPointer = false;
if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
Ty = Ptr->getPointeeType();
@@ -682,49 +745,20 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
}
if (!isPointer || !Ty->isVoidType()) {
if (RequireCompleteType(ThrowLoc, Ty,
- isPointer? diag::err_throw_incomplete_ptr
- : diag::err_throw_incomplete,
+ isPointer ? diag::err_throw_incomplete_ptr
+ : diag::err_throw_incomplete,
E->getSourceRange()))
- return ExprError();
+ return true;
- if (RequireNonAbstractType(ThrowLoc, E->getType(),
+ if (RequireNonAbstractType(ThrowLoc, ExceptionObjectTy,
diag::err_throw_abstract_type, E))
- return ExprError();
+ return true;
}
- // Initialize the exception result. This implicitly weeds out
- // abstract types or types with inaccessible copy constructors.
-
- // C++0x [class.copymove]p31:
- // When certain criteria are met, an implementation is allowed to omit the
- // copy/move construction of a class object [...]
- //
- // - in a throw-expression, when the operand is the name of a
- // non-volatile automatic object (other than a function or catch-clause
- // parameter) whose scope does not extend beyond the end of the
- // innermost enclosing try-block (if there is one), the copy/move
- // operation from the operand to the exception object (15.1) can be
- // omitted by constructing the automatic object directly into the
- // exception object
- const VarDecl *NRVOVariable = nullptr;
- if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
-
- InitializedEntity Entity =
- InitializedEntity::InitializeException(ThrowLoc, E->getType(),
- /*NRVO=*/NRVOVariable != nullptr);
- Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
- QualType(), E,
- IsThrownVarInScope);
- if (Res.isInvalid())
- return ExprError();
- E = Res.get();
-
// If the exception has class type, we need additional handling.
- const RecordType *RecordTy = Ty->getAs<RecordType>();
- if (!RecordTy)
- return E;
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
// If we are throwing a polymorphic class type or pointer thereof,
// exception handling will make use of the vtable.
@@ -732,22 +766,69 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
// If a pointer is thrown, the referenced object will not be destroyed.
if (isPointer)
- return E;
+ return false;
// If the class has a destructor, we must be able to call it.
- if (RD->hasIrrelevantDestructor())
- return E;
+ if (!RD->hasIrrelevantDestructor()) {
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
+ MarkFunctionReferenced(E->getExprLoc(), Destructor);
+ CheckDestructorAccess(E->getExprLoc(), Destructor,
+ PDiag(diag::err_access_dtor_exception) << Ty);
+ if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
+ return true;
+ }
+ }
- CXXDestructorDecl *Destructor = LookupDestructor(RD);
- if (!Destructor)
- return E;
+ // The MSVC ABI creates a list of all types which can catch the exception
+ // object. This list also references the appropriate copy constructor to call
+ // if the object is caught by value and has a non-trivial copy constructor.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // We are only interested in the public, unambiguous bases contained within
+ // the exception object. Bases which are ambiguous or otherwise
+ // inaccessible are not catchable types.
+ llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects;
+ getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects);
+
+ for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) {
+ // Attempt to lookup the copy constructor. Various pieces of machinery
+ // will spring into action, like template instantiation, which means this
+ // cannot be a simple walk of the class's decls. Instead, we must perform
+ // lookup and overload resolution.
+ CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0);
+ if (!CD)
+ continue;
- MarkFunctionReferenced(E->getExprLoc(), Destructor);
- CheckDestructorAccess(E->getExprLoc(), Destructor,
- PDiag(diag::err_access_dtor_exception) << Ty);
- if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
- return ExprError();
- return E;
+ // Mark the constructor referenced as it is used by this throw expression.
+ MarkFunctionReferenced(E->getExprLoc(), CD);
+
+ // Skip this copy constructor if it is trivial, we don't need to record it
+ // in the catchable type data.
+ if (CD->isTrivial())
+ continue;
+
+ // The copy constructor is non-trivial, create a mapping from this class
+ // type to this constructor.
+ // N.B. The selection of copy constructor is not sensitive to this
+ // particular throw-site. Lookup will be performed at the catch-site to
+ // ensure that the copy constructor is, in fact, accessible (via
+ // friendship or any other means).
+ Context.addCopyConstructorForExceptionObject(Subobject, CD);
+
+ // We don't keep the instantiated default argument expressions around so
+ // we must rebuild them here.
+ for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) {
+ // Skip any default arguments that we've already instantiated.
+ if (Context.getDefaultArgExprForConstructor(CD, I))
+ continue;
+
+ Expr *DefaultArg =
+ BuildCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)).get();
+ Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
+ }
+ }
+ }
+
+ return false;
}
QualType Sema::getCurrentThisType() {
@@ -982,18 +1063,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
Expr *Inner = Result.get();
if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner))
Inner = BTE->getSubExpr();
- if (isa<InitListExpr>(Inner)) {
- // If the list-initialization doesn't involve a constructor call, we'll get
- // the initializer-list (with corrected type) back, but that's not what we
- // want, since it will be treated as an initializer list in further
- // processing. Explicitly insert a cast here.
+ if (!isa<CXXTemporaryObjectExpr>(Inner)) {
+ // If we created a CXXTemporaryObjectExpr, that node also represents the
+ // functional cast. Otherwise, create an explicit cast to represent
+ // the syntactic form of a functional-style cast that was used here.
+ //
+ // FIXME: Creating a CXXFunctionalCastExpr around a CXXConstructExpr
+ // would give a more consistent AST representation than using a
+ // CXXTemporaryObjectExpr. It's also weird that the functional cast
+ // is sometimes handled by initialization and sometimes not.
QualType ResultType = Result.get()->getType();
Result = CXXFunctionalCastExpr::Create(
Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo,
CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc);
}
- // FIXME: Improve AST representation?
return Result;
}
@@ -1333,8 +1417,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
return S.Diag(Loc,
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_array_size_conversion
@@ -2048,7 +2133,7 @@ void Sema::DeclareGlobalNewDelete() {
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
QualType Return,
QualType Param1, QualType Param2,
- bool AddMallocAttr) {
+ bool AddRestrictAttr) {
DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
unsigned NumParams = Param2.isNull() ? 1 : 2;
@@ -2071,8 +2156,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// FIXME: Do we need to check for default arguments here?
if (InitialParam1Type == Param1 &&
(NumParams == 1 || InitialParam2Type == Param2)) {
- if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
- Func->addAttr(MallocAttr::CreateImplicit(Context));
+ if (AddRestrictAttr && !Func->hasAttr<RestrictAttr>())
+ Func->addAttr(RestrictAttr::CreateImplicit(
+ Context, RestrictAttr::GNU_malloc));
// Make the function visible to name lookup, even if we found it in
// an unimported module. It either is an implicitly-declared global
// allocation function, or is suppressing that function.
@@ -2110,9 +2196,14 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
SourceLocation(), Name,
FnType, /*TInfo=*/nullptr, SC_None, false, true);
Alloc->setImplicit();
+
+ // Implicit sized deallocation functions always have default visibility.
+ Alloc->addAttr(VisibilityAttr::CreateImplicit(Context,
+ VisibilityAttr::Default));
- if (AddMallocAttr)
- Alloc->addAttr(MallocAttr::CreateImplicit(Context));
+ if (AddRestrictAttr)
+ Alloc->addAttr(
+ RestrictAttr::CreateImplicit(Context, RestrictAttr::GNU_malloc));
ParmVarDecl *ParamDecls[2];
for (unsigned I = 0; I != NumParams; ++I) {
@@ -2247,6 +2338,260 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
return false;
}
+namespace {
+/// \brief Checks whether delete-expression, and new-expression used for
+/// initializing deletee have the same array form.
+class MismatchingNewDeleteDetector {
+public:
+ enum MismatchResult {
+ /// Indicates that there is no mismatch or a mismatch cannot be proven.
+ NoMismatch,
+ /// Indicates that variable is initialized with mismatching form of \a new.
+ VarInitMismatches,
+ /// Indicates that member is initialized with mismatching form of \a new.
+ MemberInitMismatches,
+ /// Indicates that 1 or more constructors' definitions could not been
+ /// analyzed, and they will be checked again at the end of translation unit.
+ AnalyzeLater
+ };
+
+ /// \param EndOfTU True, if this is the final analysis at the end of
+ /// translation unit. False, if this is the initial analysis at the point
+ /// delete-expression was encountered.
+ explicit MismatchingNewDeleteDetector(bool EndOfTU)
+ : IsArrayForm(false), Field(nullptr), EndOfTU(EndOfTU),
+ HasUndefinedConstructors(false) {}
+
+ /// \brief Checks whether pointee of a delete-expression is initialized with
+ /// matching form of new-expression.
+ ///
+ /// If return value is \c VarInitMismatches or \c MemberInitMismatches at the
+ /// point where delete-expression is encountered, then a warning will be
+ /// issued immediately. If return value is \c AnalyzeLater at the point where
+ /// delete-expression is seen, then member will be analyzed at the end of
+ /// translation unit. \c AnalyzeLater is returned iff at least one constructor
+ /// couldn't be analyzed. If at least one constructor initializes the member
+ /// with matching type of new, the return value is \c NoMismatch.
+ MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE);
+ /// \brief Analyzes a class member.
+ /// \param Field Class member to analyze.
+ /// \param DeleteWasArrayForm Array form-ness of the delete-expression used
+ /// for deleting the \p Field.
+ MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm);
+ /// List of mismatching new-expressions used for initialization of the pointee
+ llvm::SmallVector<const CXXNewExpr *, 4> NewExprs;
+ /// Indicates whether delete-expression was in array form.
+ bool IsArrayForm;
+ FieldDecl *Field;
+
+private:
+ const bool EndOfTU;
+ /// \brief Indicates that there is at least one constructor without body.
+ bool HasUndefinedConstructors;
+ /// \brief Returns \c CXXNewExpr from given initialization expression.
+ /// \param E Expression used for initializing pointee in delete-expression.
+ /// E can be a single-element \c InitListExpr consisting of new-expression.
+ const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E);
+ /// \brief Returns whether member is initialized with mismatching form of
+ /// \c new either by the member initializer or in-class initialization.
+ ///
+ /// If bodies of all constructors are not visible at the end of translation
+ /// unit or at least one constructor initializes member with the matching
+ /// form of \c new, mismatch cannot be proven, and this function will return
+ /// \c NoMismatch.
+ MismatchResult analyzeMemberExpr(const MemberExpr *ME);
+ /// \brief Returns whether variable is initialized with mismatching form of
+ /// \c new.
+ ///
+ /// If variable is initialized with matching form of \c new or variable is not
+ /// initialized with a \c new expression, this function will return true.
+ /// If variable is initialized with mismatching form of \c new, returns false.
+ /// \param D Variable to analyze.
+ bool hasMatchingVarInit(const DeclRefExpr *D);
+ /// \brief Checks whether the constructor initializes pointee with mismatching
+ /// form of \c new.
+ ///
+ /// Returns true, if member is initialized with matching form of \c new in
+ /// member initializer list. Returns false, if member is initialized with the
+ /// matching form of \c new in this constructor's initializer or given
+ /// constructor isn't defined at the point where delete-expression is seen, or
+ /// member isn't initialized by the constructor.
+ bool hasMatchingNewInCtor(const CXXConstructorDecl *CD);
+ /// \brief Checks whether member is initialized with matching form of
+ /// \c new in member initializer list.
+ bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI);
+ /// Checks whether member is initialized with mismatching form of \c new by
+ /// in-class initializer.
+ MismatchResult analyzeInClassInitializer();
+};
+}
+
+MismatchingNewDeleteDetector::MismatchResult
+MismatchingNewDeleteDetector::analyzeDeleteExpr(const CXXDeleteExpr *DE) {
+ NewExprs.clear();
+ assert(DE && "Expected delete-expression");
+ IsArrayForm = DE->isArrayForm();
+ const Expr *E = DE->getArgument()->IgnoreParenImpCasts();
+ if (const MemberExpr *ME = dyn_cast<const MemberExpr>(E)) {
+ return analyzeMemberExpr(ME);
+ } else if (const DeclRefExpr *D = dyn_cast<const DeclRefExpr>(E)) {
+ if (!hasMatchingVarInit(D))
+ return VarInitMismatches;
+ }
+ return NoMismatch;
+}
+
+const CXXNewExpr *
+MismatchingNewDeleteDetector::getNewExprFromInitListOrExpr(const Expr *E) {
+ assert(E != nullptr && "Expected a valid initializer expression");
+ E = E->IgnoreParenImpCasts();
+ if (const InitListExpr *ILE = dyn_cast<const InitListExpr>(E)) {
+ if (ILE->getNumInits() == 1)
+ E = dyn_cast<const CXXNewExpr>(ILE->getInit(0)->IgnoreParenImpCasts());
+ }
+
+ return dyn_cast_or_null<const CXXNewExpr>(E);
+}
+
+bool MismatchingNewDeleteDetector::hasMatchingNewInCtorInit(
+ const CXXCtorInitializer *CI) {
+ const CXXNewExpr *NE = nullptr;
+ if (Field == CI->getMember() &&
+ (NE = getNewExprFromInitListOrExpr(CI->getInit()))) {
+ if (NE->isArray() == IsArrayForm)
+ return true;
+ else
+ NewExprs.push_back(NE);
+ }
+ return false;
+}
+
+bool MismatchingNewDeleteDetector::hasMatchingNewInCtor(
+ const CXXConstructorDecl *CD) {
+ if (CD->isImplicit())
+ return false;
+ const FunctionDecl *Definition = CD;
+ if (!CD->isThisDeclarationADefinition() && !CD->isDefined(Definition)) {
+ HasUndefinedConstructors = true;
+ return EndOfTU;
+ }
+ for (const auto *CI : cast<const CXXConstructorDecl>(Definition)->inits()) {
+ if (hasMatchingNewInCtorInit(CI))
+ return true;
+ }
+ return false;
+}
+
+MismatchingNewDeleteDetector::MismatchResult
+MismatchingNewDeleteDetector::analyzeInClassInitializer() {
+ assert(Field != nullptr && "This should be called only for members");
+ if (const CXXNewExpr *NE =
+ getNewExprFromInitListOrExpr(Field->getInClassInitializer())) {
+ if (NE->isArray() != IsArrayForm) {
+ NewExprs.push_back(NE);
+ return MemberInitMismatches;
+ }
+ }
+ return NoMismatch;
+}
+
+MismatchingNewDeleteDetector::MismatchResult
+MismatchingNewDeleteDetector::analyzeField(FieldDecl *Field,
+ bool DeleteWasArrayForm) {
+ assert(Field != nullptr && "Analysis requires a valid class member.");
+ this->Field = Field;
+ IsArrayForm = DeleteWasArrayForm;
+ const CXXRecordDecl *RD = cast<const CXXRecordDecl>(Field->getParent());
+ for (const auto *CD : RD->ctors()) {
+ if (hasMatchingNewInCtor(CD))
+ return NoMismatch;
+ }
+ if (HasUndefinedConstructors)
+ return EndOfTU ? NoMismatch : AnalyzeLater;
+ if (!NewExprs.empty())
+ return MemberInitMismatches;
+ return Field->hasInClassInitializer() ? analyzeInClassInitializer()
+ : NoMismatch;
+}
+
+MismatchingNewDeleteDetector::MismatchResult
+MismatchingNewDeleteDetector::analyzeMemberExpr(const MemberExpr *ME) {
+ assert(ME != nullptr && "Expected a member expression");
+ if (FieldDecl *F = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ return analyzeField(F, IsArrayForm);
+ return NoMismatch;
+}
+
+bool MismatchingNewDeleteDetector::hasMatchingVarInit(const DeclRefExpr *D) {
+ const CXXNewExpr *NE = nullptr;
+ if (const VarDecl *VD = dyn_cast<const VarDecl>(D->getDecl())) {
+ if (VD->hasInit() && (NE = getNewExprFromInitListOrExpr(VD->getInit())) &&
+ NE->isArray() != IsArrayForm) {
+ NewExprs.push_back(NE);
+ }
+ }
+ return NewExprs.empty();
+}
+
+static void
+DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc,
+ const MismatchingNewDeleteDetector &Detector) {
+ SourceLocation EndOfDelete = SemaRef.getLocForEndOfToken(DeleteLoc);
+ FixItHint H;
+ if (!Detector.IsArrayForm)
+ H = FixItHint::CreateInsertion(EndOfDelete, "[]");
+ else {
+ SourceLocation RSquare = Lexer::findLocationAfterToken(
+ DeleteLoc, tok::l_square, SemaRef.getSourceManager(),
+ SemaRef.getLangOpts(), true);
+ if (RSquare.isValid())
+ H = FixItHint::CreateRemoval(SourceRange(EndOfDelete, RSquare));
+ }
+ SemaRef.Diag(DeleteLoc, diag::warn_mismatched_delete_new)
+ << Detector.IsArrayForm << H;
+
+ for (const auto *NE : Detector.NewExprs)
+ SemaRef.Diag(NE->getExprLoc(), diag::note_allocated_here)
+ << Detector.IsArrayForm;
+}
+
+void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) {
+ if (Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation()))
+ return;
+ MismatchingNewDeleteDetector Detector(/*EndOfTU=*/false);
+ switch (Detector.analyzeDeleteExpr(DE)) {
+ case MismatchingNewDeleteDetector::VarInitMismatches:
+ case MismatchingNewDeleteDetector::MemberInitMismatches: {
+ DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector);
+ break;
+ }
+ case MismatchingNewDeleteDetector::AnalyzeLater: {
+ DeleteExprs[Detector.Field].push_back(
+ std::make_pair(DE->getLocStart(), DE->isArrayForm()));
+ break;
+ }
+ case MismatchingNewDeleteDetector::NoMismatch:
+ break;
+ }
+}
+
+void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
+ bool DeleteWasArrayForm) {
+ MismatchingNewDeleteDetector Detector(/*EndOfTU=*/true);
+ switch (Detector.analyzeField(Field, DeleteWasArrayForm)) {
+ case MismatchingNewDeleteDetector::VarInitMismatches:
+ llvm_unreachable("This analysis should have been done for class members.");
+ case MismatchingNewDeleteDetector::AnalyzeLater:
+ llvm_unreachable("Analysis cannot be postponed any point beyond end of "
+ "translation unit.");
+ case MismatchingNewDeleteDetector::MemberInitMismatches:
+ DiagnoseMismatchedNewDelete(*this, DeleteLoc, Detector);
+ break;
+ case MismatchingNewDeleteDetector::NoMismatch:
+ break;
+ }
+}
+
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
/// @code ::delete ptr; @endcode
/// or
@@ -2362,12 +2707,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
}
- // C++ [expr.delete]p2:
- // [Note: a pointer to a const type can be the operand of a
- // delete-expression; it is not necessary to cast away the constness
- // (5.2.11) of the pointer expression before it is used as the operand
- // of the delete-expression. ]
-
if (Pointee->isArrayType() && !ArrayForm) {
Diag(StartLoc, diag::warn_delete_array_type)
<< Type << Ex.get()->getSourceRange()
@@ -2442,7 +2781,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
DeleteName);
MarkFunctionReferenced(StartLoc, OperatorDelete);
-
+
// Check access and ambiguity of operator delete and destructor.
if (PointeeRD) {
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
@@ -2452,9 +2791,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
}
- return new (Context) CXXDeleteExpr(
+ CXXDeleteExpr *Result = new (Context) CXXDeleteExpr(
Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten,
UsualArrayDeleteWantsSize, OperatorDelete, Ex.get(), StartLoc);
+ AnalyzeDeleteExprMismatch(Result);
+ return Result;
}
/// \brief Check the use of the given variable as a C++ condition in an if,
@@ -2570,6 +2911,8 @@ static ExprResult BuildCXXCastArgument(Sema &S,
S.CheckConstructorAccess(CastLoc, Constructor,
InitializedEntity::InitializeTemporary(Ty),
Constructor->getAccess());
+ if (S.DiagnoseUseOfDecl(Method, CastLoc))
+ return ExprError();
ExprResult Result = S.BuildCXXConstructExpr(
CastLoc, Ty, cast<CXXConstructorDecl>(Method),
@@ -2585,6 +2928,10 @@ static ExprResult BuildCXXCastArgument(Sema &S,
case CK_UserDefinedConversion: {
assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
+ S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl);
+ if (S.DiagnoseUseOfDecl(Method, CastLoc))
+ return ExprError();
+
// Create an implicit call expr that calls it.
CXXConversionDecl *Conv = cast<CXXConversionDecl>(Method);
ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Conv,
@@ -2596,8 +2943,6 @@ static ExprResult BuildCXXCastArgument(Sema &S,
CK_UserDefinedConversion, Result.get(),
nullptr, Result.get()->getValueKind());
- S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl);
-
return S.MaybeBindToTemporary(Result.get());
}
}
@@ -2628,7 +2973,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
CastKind CastKind;
QualType BeforeToType;
- assert(FD && "FIXME: aggregate initialization from init list");
+ assert(FD && "no conversion function for user-defined conversion seq");
if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
CastKind = CK_UserDefinedConversion;
@@ -2945,10 +3290,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// We may not have been able to figure out what this member pointer resolved
// to up until this exact point. Attempt to lock-in it's inheritance model.
- QualType FromType = From->getType();
- if (FromType->isMemberPointerType())
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(From->getExprLoc(), FromType, 0);
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ RequireCompleteType(From->getExprLoc(), From->getType(), 0);
+ RequireCompleteType(From->getExprLoc(), ToType, 0);
+ }
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
.get();
@@ -2989,8 +3334,18 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
break;
case ICK_Vector_Splat:
- From = ImpCastExprToType(From, ToType, CK_VectorSplat,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ // Vector splat from any arithmetic type to a vector.
+ // Cast to the element type.
+ {
+ QualType elType = ToType->getAs<ExtVectorType>()->getElementType();
+ if (elType != From->getType()) {
+ ExprResult E = From;
+ From = ImpCastExprToType(From, elType,
+ PrepareScalarCast(E, elType)).get();
+ }
+ From = ImpCastExprToType(From, ToType, CK_VectorSplat,
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ }
break;
case ICK_Complex_Real:
@@ -3529,8 +3884,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
bool FoundConstructor = false;
unsigned FoundTQs;
- DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_const_iterator Con = R.begin(),
+ DeclContext::lookup_result R = Self.LookupConstructors(RD);
+ for (DeclContext::lookup_iterator Con = R.begin(),
ConEnd = R.end(); Con != ConEnd; ++Con) {
// A template constructor is never a copy constructor.
// FIXME: However, it may actually be selected at the actual overload
@@ -3569,8 +3924,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return true;
bool FoundConstructor = false;
- DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_const_iterator Con = R.begin(),
+ DeclContext::lookup_result R = Self.LookupConstructors(RD);
+ for (DeclContext::lookup_iterator Con = R.begin(),
ConEnd = R.end(); Con != ConEnd; ++Con) {
// FIXME: In C++0x, a constructor template can be a default constructor.
if (isa<FunctionTemplateDecl>(*Con))
@@ -5139,7 +5494,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
if (Call == TopCall)
continue;
- if (CheckCallReturnType(Call->getCallReturnType(),
+ if (CheckCallReturnType(Call->getCallReturnType(Context),
Call->getLocStart(),
Call, Call->getDirectCallee()))
return ExprError();
@@ -5202,10 +5557,11 @@ static void noteOperatorArrows(Sema &S,
}
}
-ExprResult
-Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, ParsedType &ObjectType,
- bool &MayBePseudoDestructor) {
+ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor) {
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
if (Result.isInvalid()) return ExprError();
@@ -5339,20 +5695,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
return Base;
}
-ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
- Expr *MemExpr) {
- SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc);
- Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call)
- << isa<CXXPseudoDestructorExpr>(MemExpr)
- << FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
-
- return ActOnCallExpr(/*Scope*/ nullptr,
- MemExpr,
- /*LPLoc*/ ExpectedLParenLoc,
- None,
- /*RPLoc*/ ExpectedLParenLoc);
-}
-
static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
tok::TokenKind& OpKind, SourceLocation OpLoc) {
if (Base->hasPlaceholderType()) {
@@ -5393,8 +5735,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
TypeSourceInfo *ScopeTypeInfo,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- PseudoDestructorTypeStorage Destructed,
- bool HasTrailingLParen) {
+ PseudoDestructorTypeStorage Destructed) {
TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
QualType ObjectType;
@@ -5482,10 +5823,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
TildeLoc,
Destructed);
- if (HasTrailingLParen)
- return Result;
-
- return DiagnoseDtorReference(Destructed.getLocation(), Result);
+ return Result;
}
ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
@@ -5495,8 +5833,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
UnqualifiedId &FirstTypeName,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
+ UnqualifiedId &SecondTypeName) {
assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
"Invalid first type name in pseudo-destructor");
@@ -5623,15 +5960,14 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS,
ScopeTypeInfo, CCLoc, TildeLoc,
- Destructed, HasTrailingLParen);
+ Destructed);
}
ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation TildeLoc,
- const DeclSpec& DS,
- bool HasTrailingLParen) {
+ const DeclSpec& DS) {
QualType ObjectType;
if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
return ExprError();
@@ -5647,7 +5983,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(),
nullptr, SourceLocation(), TildeLoc,
- Destructed, HasTrailingLParen);
+ Destructed);
}
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
@@ -5685,10 +6021,9 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
if (Exp.isInvalid())
return true;
- MemberExpr *ME =
- new (Context) MemberExpr(Exp.get(), /*IsArrow=*/false, Method,
- SourceLocation(), Context.BoundMemberTy,
- VK_RValue, OK_Ordinary);
+ MemberExpr *ME = new (Context) MemberExpr(
+ Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(),
+ Context.BoundMemberTy, VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
@@ -6052,6 +6387,8 @@ public:
class TransformTypos : public TreeTransform<TransformTypos> {
typedef TreeTransform<TransformTypos> BaseTransform;
+ VarDecl *InitDecl; // A decl to avoid as a correction because it is in the
+ // process of being initialized.
llvm::function_ref<ExprResult(Expr *)> ExprFilter;
llvm::SmallSetVector<TypoExpr *, 2> TypoExprs, AmbiguousTypoExprs;
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
@@ -6130,8 +6467,8 @@ class TransformTypos : public TreeTransform<TransformTypos> {
}
public:
- TransformTypos(Sema &SemaRef, llvm::function_ref<ExprResult(Expr *)> Filter)
- : BaseTransform(SemaRef), ExprFilter(Filter) {}
+ TransformTypos(Sema &SemaRef, VarDecl *InitDecl, llvm::function_ref<ExprResult(Expr *)> Filter)
+ : BaseTransform(SemaRef), InitDecl(InitDecl), ExprFilter(Filter) {}
ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
MultiExprArg Args,
@@ -6169,6 +6506,11 @@ public:
// with the same edit length that pass all the checks and filters.
// TODO: Properly handle various permutations of possible corrections when
// there is more than one potentially ambiguous typo correction.
+ // Also, disable typo correction while attempting the transform when
+ // handling potentially ambiguous typo corrections as any new TypoExprs will
+ // have been introduced by the application of one of the correction
+ // candidates and add little to no value if corrected.
+ SemaRef.DisableTypoCorrection = true;
while (!AmbiguousTypoExprs.empty()) {
auto TE = AmbiguousTypoExprs.back();
auto Cached = TransformCache[TE];
@@ -6185,6 +6527,7 @@ public:
State.Consumer->restoreSavedPosition();
TransformCache[TE] = Cached;
}
+ SemaRef.DisableTypoCorrection = false;
// Ensure that all of the TypoExprs within the current Expr have been found.
if (!Res.isUsable())
@@ -6210,6 +6553,8 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
+ if (InitDecl && TC.getCorrectionDecl() == InitDecl)
+ continue;
ExprResult NE = State.RecoveryHandler ?
State.RecoveryHandler(SemaRef, E, TC) :
attemptRecovery(SemaRef, *State.Consumer, TC);
@@ -6234,8 +6579,9 @@ public:
};
}
-ExprResult Sema::CorrectDelayedTyposInExpr(
- Expr *E, llvm::function_ref<ExprResult(Expr *)> Filter) {
+ExprResult
+Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
+ llvm::function_ref<ExprResult(Expr *)> Filter) {
// If the current evaluation context indicates there are uncorrected typos
// and the current expression isn't guaranteed to not have typos, try to
// resolve any TypoExpr nodes that might be in the expression.
@@ -6246,7 +6592,7 @@ ExprResult Sema::CorrectDelayedTyposInExpr(
assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr");
ExprEvalContexts.back().NumTypos = ~0U;
auto TyposResolved = DelayedTypos.size();
- auto Result = TransformTypos(*this, Filter).Transform(E);
+ auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E);
ExprEvalContexts.back().NumTypos = TyposInContext;
TyposResolved -= DelayedTypos.size();
if (Result.isInvalid() || Result.get() != E) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index af1cf90..a9f1919 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -109,9 +109,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
NamedDecl *D = *I;
if (D->isCXXInstanceMember()) {
- if (dyn_cast<FieldDecl>(D) || dyn_cast<MSPropertyDecl>(D)
- || dyn_cast<IndirectFieldDecl>(D))
- isField = true;
+ isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
+ isa<IndirectFieldDecl>(D);
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
Classes.insert(R->getCanonicalDecl());
@@ -732,8 +731,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- const CXXScopeSpec &SS, FieldDecl *Field,
- DeclAccessPair FoundDecl,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ FieldDecl *Field, DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo);
ExprResult
@@ -820,10 +819,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
-
+
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
- EmptySS, field, foundDecl,
- memberNameInfo).get();
+ SourceLocation(), EmptySS, field,
+ foundDecl, memberNameInfo).get();
if (!result)
return ExprError();
@@ -841,9 +840,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
DeclAccessPair fakeFoundDecl =
DeclAccessPair::make(field, field->getAccess());
- result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
- (FI == FEnd? SS : EmptySS), field,
- fakeFoundDecl, memberNameInfo).get();
+ result =
+ BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
+ SourceLocation(), (FI == FEnd ? SS : EmptySS),
+ field, fakeFoundDecl, memberNameInfo).get();
}
return result;
@@ -863,18 +863,16 @@ BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
}
/// \brief Build a MemberExpr AST node.
-static MemberExpr *
-BuildMemberExpr(Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
- const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- ValueDecl *Member, DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo, QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = nullptr) {
+static MemberExpr *BuildMemberExpr(
+ Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
+ SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK,
+ ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr) {
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
- MemberExpr *E =
- MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
- TemplateKWLoc, Member, FoundDecl, MemberNameInfo,
- TemplateArgs, Ty, VK, OK);
+ MemberExpr *E = MemberExpr::Create(
+ C, Base, isArrow, OpLoc, SS.getWithLocInContext(C), TemplateKWLoc, Member,
+ FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK);
SemaRef.MarkMemberReferenced(E);
return E;
}
@@ -969,8 +967,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
CXXScopeSpec TempSS(SS);
RetryExpr = ActOnMemberAccessExpr(
ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
- TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl,
- ExtraArgs->HasTrailingLParen);
+ TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
}
if (Trap.hasErrorOccurred())
RetryExpr = ExprError();
@@ -1058,8 +1055,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
- return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
- SS, FD, FoundDecl, MemberNameInfo);
+ return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, OpLoc, SS, FD,
+ FoundDecl, MemberNameInfo);
if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
@@ -1073,8 +1070,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Var, FoundDecl, MemberNameInfo,
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, Var, FoundDecl, MemberNameInfo,
Var->getType().getNonReferenceType(), VK_LValue,
OK_Ordinary);
}
@@ -1090,16 +1087,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
type = MemberFn->getType();
}
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- MemberFn, FoundDecl, MemberNameInfo, type, valueKind,
- OK_Ordinary);
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, MemberFn, FoundDecl, MemberNameInfo,
+ type, valueKind, OK_Ordinary);
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Enum, FoundDecl, MemberNameInfo, Enum->getType(),
- VK_RValue, OK_Ordinary);
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, Enum, FoundDecl, MemberNameInfo,
+ Enum->getType(), VK_RValue, OK_Ordinary);
}
// We found something that we didn't expect. Complain.
@@ -1381,7 +1378,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}
ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
- IV, IV->getType(), MemberLoc, OpLoc, BaseExpr.get(), IsArrow);
+ IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),
+ IsArrow);
if (S.getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
@@ -1521,7 +1519,15 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (BaseType->isExtVectorType()) {
// FIXME: this expr should store IsArrow.
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
- ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
+ ExprValueKind VK;
+ if (IsArrow)
+ VK = VK_LValue;
+ else {
+ if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(BaseExpr.get()))
+ VK = POE->getSyntacticForm()->getValueKind();
+ else
+ VK = BaseExpr.get()->getValueKind();
+ }
QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
@@ -1591,9 +1597,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
/// possibilities, including destructor and operator references.
///
/// \param OpKind either tok::arrow or tok::period
-/// \param HasTrailingLParen whether the next token is '(', which
-/// is used to diagnose mis-uses of special members that can
-/// only be called
/// \param ObjCImpDecl the current Objective-C \@implementation
/// decl; this is an ugly hack around the fact that Objective-C
/// \@implementations aren't properly put in the context chain
@@ -1603,24 +1606,10 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
- Decl *ObjCImpDecl,
- bool HasTrailingLParen) {
+ Decl *ObjCImpDecl) {
if (SS.isSet() && SS.isInvalid())
return ExprError();
- // The only way a reference to a destructor can be used is to
- // immediately call it. If the next token is not a '(', produce
- // a diagnostic and build the call now.
- if (!HasTrailingLParen &&
- Id.getKind() == UnqualifiedId::IK_DestructorName) {
- ExprResult DtorAccess =
- ActOnMemberAccessExpr(S, Base, OpLoc, OpKind, SS, TemplateKWLoc, Id,
- ObjCImpDecl, /*HasTrailingLParen*/true);
- if (DtorAccess.isInvalid())
- return DtorAccess;
- return DiagnoseDtorReference(Id.getLocStart(), DtorAccess.get());
- }
-
// Warn about the explicit constructor calls Microsoft extension.
if (getLangOpts().MicrosoftExt &&
Id.getKind() == UnqualifiedId::IK_ConstructorName)
@@ -1653,8 +1642,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
NameInfo, TemplateArgs);
}
- ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl,
- HasTrailingLParen};
+ ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS,
TemplateKWLoc, FirstQualifierInScope,
NameInfo, TemplateArgs, &ExtraArgs);
@@ -1662,8 +1650,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- const CXXScopeSpec &SS, FieldDecl *Field,
- DeclAccessPair FoundDecl,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ FieldDecl *Field, DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo) {
// x.a is an l-value if 'a' has a reference type. Otherwise:
// x.a is an l-value/x-value/pr-value if the base is (and note
@@ -1716,7 +1704,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
FoundDecl, Field);
if (Base.isInvalid())
return ExprError();
- return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, SS,
+ return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS,
/*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
MemberNameInfo, MemberType, VK, OK);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index 9c3b51c..6cd0626 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -133,7 +133,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
ObjCInterfaceDecl::Create (Context,
Context.getTranslationUnitDecl(),
SourceLocation(), NSIdent,
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
Ty = Context.getObjCInterfaceType(NSStringIDecl);
Context.setObjCNSStringType(Ty);
}
@@ -208,7 +208,8 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
CX.getTranslationUnitDecl(),
SourceLocation(), NSNumberId,
- nullptr, SourceLocation());
+ nullptr, nullptr,
+ SourceLocation());
} else {
// Otherwise, require a declaration of NSNumber.
S.Diag(Loc, diag::err_undeclared_nsnumber);
@@ -218,7 +219,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
S.Diag(Loc, diag::err_undeclared_nsnumber);
return nullptr;
}
-
+ }
+
+ if (S.NSNumberPointer.isNull()) {
// generate the pointer to NSNumber type.
QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);
S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);
@@ -473,7 +476,8 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
SourceLocation(),
NSStringId,
- nullptr, SourceLocation());
+ nullptr, nullptr,
+ SourceLocation());
} else {
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
@@ -561,7 +565,6 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// Look for the appropriate method within NSNumber.
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
BoxedType = NSNumberPointer;
-
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
if (!ET->getDecl()->isComplete()) {
Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
@@ -572,6 +575,110 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
ET->getDecl()->getIntegerType());
BoxedType = NSNumberPointer;
+ } else if (ValueType->isObjCBoxableRecordType()) {
+ // Support for structure types, that marked as objc_boxable
+ // struct __attribute__((objc_boxable)) s { ... };
+
+ // Look up the NSValue class, if we haven't done so already. It's cached
+ // in the Sema instance.
+ if (!NSValueDecl) {
+ IdentifierInfo *NSValueId =
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
+ NamedDecl *IF = LookupSingleName(TUScope, NSValueId,
+ SR.getBegin(), Sema::LookupOrdinaryName);
+ NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!NSValueDecl) {
+ if (getLangOpts().DebuggerObjCLiteral) {
+ // Create a stub definition of NSValue.
+ DeclContext *TU = Context.getTranslationUnitDecl();
+ NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
+ SourceLocation(), NSValueId,
+ nullptr, nullptr,
+ SourceLocation());
+ } else {
+ // Otherwise, require a declaration of NSValue.
+ Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
+ return ExprError();
+ }
+ } else if (!NSValueDecl->hasDefinition()) {
+ Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
+ return ExprError();
+ }
+
+ // generate the pointer to NSValue type.
+ QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
+ NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
+ }
+
+ if (!ValueWithBytesObjCTypeMethod) {
+ IdentifierInfo *II[] = {
+ &Context.Idents.get("valueWithBytes"),
+ &Context.Idents.get("objCType")
+ };
+ Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);
+
+ // Look for the appropriate method within NSValue.
+ BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);
+ if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
+ // Debugger needs to work even if NSValue hasn't been defined.
+ TypeSourceInfo *ReturnTInfo = nullptr;
+ ObjCMethodDecl *M = ObjCMethodDecl::Create(
+ Context,
+ SourceLocation(),
+ SourceLocation(),
+ ValueWithBytesObjCType,
+ NSValuePointer,
+ ReturnTInfo,
+ NSValueDecl,
+ /*isInstance=*/false,
+ /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false,
+ ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
+
+ SmallVector<ParmVarDecl *, 2> Params;
+
+ ParmVarDecl *bytes =
+ ParmVarDecl::Create(Context, M,
+ SourceLocation(), SourceLocation(),
+ &Context.Idents.get("bytes"),
+ Context.VoidPtrTy.withConst(),
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
+ Params.push_back(bytes);
+
+ QualType ConstCharType = Context.CharTy.withConst();
+ ParmVarDecl *type =
+ ParmVarDecl::Create(Context, M,
+ SourceLocation(), SourceLocation(),
+ &Context.Idents.get("type"),
+ Context.getPointerType(ConstCharType),
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
+ Params.push_back(type);
+
+ M->setMethodParams(Context, Params, None);
+ BoxingMethod = M;
+ }
+
+ if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl,
+ ValueWithBytesObjCType, BoxingMethod))
+ return ExprError();
+
+ ValueWithBytesObjCTypeMethod = BoxingMethod;
+ }
+
+ if (!ValueType.isTriviallyCopyableType(Context)) {
+ Diag(SR.getBegin(),
+ diag::err_objc_non_trivially_copyable_boxed_expression_type)
+ << ValueType << ValueExpr->getSourceRange();
+ return ExprError();
+ }
+
+ BoxingMethod = ValueWithBytesObjCTypeMethod;
+ BoxedType = NSValuePointer;
}
if (!BoxingMethod) {
@@ -580,13 +687,22 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
return ExprError();
}
- // Convert the expression to the type that the parameter requires.
- ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- ParamDecl);
- ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity,
- SourceLocation(),
- ValueExpr);
+ DiagnoseUseOfDecl(BoxingMethod, SR.getBegin());
+
+ ExprResult ConvertedValueExpr;
+ if (ValueType->isObjCBoxableRecordType()) {
+ InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);
+ ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(),
+ ValueExpr);
+ } else {
+ // Convert the expression to the type that the parameter requires.
+ ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
+ InitializedEntity IE = InitializedEntity::InitializeParameter(Context,
+ ParamDecl);
+ ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(),
+ ValueExpr);
+ }
+
if (ConvertedValueExpr.isInvalid())
return ExprError();
ValueExpr = ConvertedValueExpr.get();
@@ -642,7 +758,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
if (!NSArrayDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
@@ -757,7 +873,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- nullptr, SourceLocation());
+ nullptr, nullptr, SourceLocation());
if (!NSDictionaryDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
@@ -843,8 +959,11 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
QIDNSCopying =
- Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl**) PQ,1);
+ Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
+ llvm::makeArrayRef(
+ (ObjCProtocolDecl**) PQ,
+ 1),
+ false);
QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
}
}
@@ -1041,7 +1160,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation RParenLoc,
bool WarnMultipleSelectors) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LParenLoc, RParenLoc), false, false);
+ SourceRange(LParenLoc, RParenLoc));
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc));
@@ -1059,15 +1178,11 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
} else
DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,
WarnMultipleSelectors);
-
+
if (Method &&
Method->getImplementationControl() != ObjCMethodDecl::Optional &&
- !getSourceManager().isInSystemHeader(Method->getLocation())) {
- llvm::DenseMap<Selector, SourceLocation>::iterator Pos
- = ReferencedSelectors.find(Sel);
- if (Pos == ReferencedSelectors.end())
- ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));
- }
+ !getSourceManager().isInSystemHeader(Method->getLocation()))
+ ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));
// In ARC, forbid the user from using @selector for
// retain/release/autorelease/dealloc/retainCount.
@@ -1137,49 +1252,156 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) {
}
static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
+ QualType origType = T;
+ if (auto nullability = AttributedType::stripOuterNullability(T)) {
+ if (T == Context.getObjCInstanceType()) {
+ return Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*nullability),
+ Context.getObjCIdType(),
+ Context.getObjCIdType());
+ }
+
+ return origType;
+ }
+
if (T == Context.getObjCInstanceType())
return Context.getObjCIdType();
- return T;
+ return origType;
}
-QualType Sema::getMessageSendResultType(QualType ReceiverType,
- ObjCMethodDecl *Method,
- bool isClassMessage, bool isSuperMessage) {
+/// Determine the result type of a message send based on the receiver type,
+/// method, and the kind of message send.
+///
+/// This is the "base" result type, which will still need to be adjusted
+/// to account for nullability.
+static QualType getBaseMessageSendResultType(Sema &S,
+ QualType ReceiverType,
+ ObjCMethodDecl *Method,
+ bool isClassMessage,
+ bool isSuperMessage) {
assert(Method && "Must have a method");
if (!Method->hasRelatedResultType())
- return Method->getSendResultType();
-
+ return Method->getSendResultType(ReceiverType);
+
+ ASTContext &Context = S.Context;
+
+ // Local function that transfers the nullability of the method's
+ // result type to the returned result.
+ auto transferNullability = [&](QualType type) -> QualType {
+ // If the method's result type has nullability, extract it.
+ if (auto nullability = Method->getSendResultType(ReceiverType)
+ ->getNullability(Context)){
+ // Strip off any outer nullability sugar from the provided type.
+ (void)AttributedType::stripOuterNullability(type);
+
+ // Form a new attributed type using the method result type's nullability.
+ return Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*nullability),
+ type,
+ type);
+ }
+
+ return type;
+ };
+
// If a method has a related return type:
// - if the method found is an instance method, but the message send
// was a class message send, T is the declared return type of the method
// found
if (Method->isInstanceMethod() && isClassMessage)
- return stripObjCInstanceType(Context, Method->getSendResultType());
-
- // - if the receiver is super, T is a pointer to the class of the
+ return stripObjCInstanceType(Context,
+ Method->getSendResultType(ReceiverType));
+
+ // - if the receiver is super, T is a pointer to the class of the
// enclosing method definition
if (isSuperMessage) {
- if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
- if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface())
- return Context.getObjCObjectPointerType(
- Context.getObjCInterfaceType(Class));
+ if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())
+ if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {
+ return transferNullability(
+ Context.getObjCObjectPointerType(
+ Context.getObjCInterfaceType(Class)));
+ }
}
-
+
// - if the receiver is the name of a class U, T is a pointer to U
- if (ReceiverType->getAs<ObjCInterfaceType>() ||
- ReceiverType->isObjCQualifiedInterfaceType())
- return Context.getObjCObjectPointerType(ReceiverType);
- // - if the receiver is of type Class or qualified Class type,
+ if (ReceiverType->getAsObjCInterfaceType())
+ return transferNullability(Context.getObjCObjectPointerType(ReceiverType));
+ // - if the receiver is of type Class or qualified Class type,
// T is the declared return type of the method.
if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType())
- return stripObjCInstanceType(Context, Method->getSendResultType());
-
+ return stripObjCInstanceType(Context,
+ Method->getSendResultType(ReceiverType));
+
// - if the receiver is id, qualified id, Class, or qualified Class, T
// is the receiver type, otherwise
// - T is the type of the receiver expression.
- return ReceiverType;
+ return transferNullability(ReceiverType);
+}
+
+QualType Sema::getMessageSendResultType(QualType ReceiverType,
+ ObjCMethodDecl *Method,
+ bool isClassMessage,
+ bool isSuperMessage) {
+ // Produce the result type.
+ QualType resultType = getBaseMessageSendResultType(*this, ReceiverType,
+ Method,
+ isClassMessage,
+ isSuperMessage);
+
+ // If this is a class message, ignore the nullability of the receiver.
+ if (isClassMessage)
+ return resultType;
+
+ // Map the nullability of the result into a table index.
+ unsigned receiverNullabilityIdx = 0;
+ if (auto nullability = ReceiverType->getNullability(Context))
+ receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+
+ unsigned resultNullabilityIdx = 0;
+ if (auto nullability = resultType->getNullability(Context))
+ resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+
+ // The table of nullability mappings, indexed by the receiver's nullability
+ // and then the result type's nullability.
+ static const uint8_t None = 0;
+ static const uint8_t NonNull = 1;
+ static const uint8_t Nullable = 2;
+ static const uint8_t Unspecified = 3;
+ static const uint8_t nullabilityMap[4][4] = {
+ // None NonNull Nullable Unspecified
+ /* None */ { None, None, Nullable, None },
+ /* NonNull */ { None, NonNull, Nullable, Unspecified },
+ /* Nullable */ { Nullable, Nullable, Nullable, Nullable },
+ /* Unspecified */ { None, Unspecified, Nullable, Unspecified }
+ };
+
+ unsigned newResultNullabilityIdx
+ = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];
+ if (newResultNullabilityIdx == resultNullabilityIdx)
+ return resultType;
+
+ // Strip off the existing nullability. This removes as little type sugar as
+ // possible.
+ do {
+ if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) {
+ resultType = attributed->getModifiedType();
+ } else {
+ resultType = resultType.getDesugaredType(Context);
+ }
+ } while (resultType->getNullability(Context));
+
+ // Add nullability back if needed.
+ if (newResultNullabilityIdx > 0) {
+ auto newNullability
+ = static_cast<NullabilityKind>(newResultNullabilityIdx-1);
+ return Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(newNullability),
+ resultType, resultType);
+ }
+
+ return resultType;
}
/// Look for an ObjC method whose result type exactly matches the given type.
@@ -1373,6 +1595,10 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return false;
}
+ // Compute the set of type arguments to be substituted into each parameter
+ // type.
+ Optional<ArrayRef<QualType>> typeArgs
+ = ReceiverType->getObjCSubstitutions(Method->getDeclContext());
bool IsError = false;
for (unsigned i = 0; i < NumNamedArgs; i++) {
// We can't do any type-checking on a type-dependent argument.
@@ -1406,18 +1632,37 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
continue;
}
+ QualType origParamType = param->getType();
+ QualType paramType = param->getType();
+ if (typeArgs)
+ paramType = paramType.substObjCTypeArgs(
+ Context,
+ *typeArgs,
+ ObjCSubstitutionContext::Parameter);
+
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
- param->getType(),
+ paramType,
diag::err_call_incomplete_argument, argExpr))
return true;
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- param);
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Context, param, paramType);
ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr);
if (ArgE.isInvalid())
IsError = true;
- else
+ else {
Args[i] = ArgE.getAs<Expr>();
+
+ // If we are type-erasing a block to a block-compatible
+ // Objective-C pointer type, we may need to extend the lifetime
+ // of the block object.
+ if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
+ origParamType->isBlockCompatibleObjCPointerType(Context)) {
+ ExprResult arg = Args[i];
+ maybeExtendBlockObject(arg);
+ Args[i] = arg.get();
+ }
+ }
}
// Promote additional arguments to variadic methods.
@@ -1507,64 +1752,6 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
return nullptr;
}
-static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
- if (!Receiver)
- return;
-
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Receiver))
- Receiver = OVE->getSourceExpr();
-
- Expr *RExpr = Receiver->IgnoreParenImpCasts();
- SourceLocation Loc = RExpr->getLocStart();
- QualType T = RExpr->getType();
- const ObjCPropertyDecl *PDecl = nullptr;
- const ObjCMethodDecl *GDecl = nullptr;
- if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) {
- RExpr = POE->getSyntacticForm();
- if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) {
- if (PRE->isImplicitProperty()) {
- GDecl = PRE->getImplicitPropertyGetter();
- if (GDecl) {
- T = GDecl->getReturnType();
- }
- }
- else {
- PDecl = PRE->getExplicitProperty();
- if (PDecl) {
- T = PDecl->getType();
- }
- }
- }
- }
- else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RExpr)) {
- // See if receiver is a method which envokes a synthesized getter
- // backing a 'weak' property.
- ObjCMethodDecl *Method = ME->getMethodDecl();
- if (Method && Method->getSelector().getNumArgs() == 0) {
- PDecl = Method->findPropertyDecl();
- if (PDecl)
- T = PDecl->getType();
- }
- }
-
- if (T.getObjCLifetime() != Qualifiers::OCL_Weak) {
- if (!PDecl)
- return;
- if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak))
- return;
- }
-
- S.Diag(Loc, diag::warn_receiver_is_weak)
- << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2));
-
- if (PDecl)
- S.Diag(PDecl->getLocation(), diag::note_property_declare);
- else if (GDecl)
- S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl;
-
- S.Diag(Loc, diag::note_arc_assign_to_strong);
-}
-
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
/// objective C interface. This is a property reference expression.
ExprResult Sema::
@@ -1743,37 +1930,35 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
receiverNameLoc);
- bool IsSuper = false;
+ QualType SuperType;
if (!IFace) {
// If the "receiver" is 'super' in a method, handle it as an expression-like
// property reference.
if (receiverNamePtr->isStr("super")) {
- IsSuper = true;
-
if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
- if (CurMethod->isInstanceMethod()) {
- ObjCInterfaceDecl *Super =
- CurMethod->getClassInterface()->getSuperClass();
- if (!Super) {
- // The current class does not have a superclass.
- Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
- << CurMethod->getClassInterface()->getIdentifier();
- return ExprError();
+ if (auto classDecl = CurMethod->getClassInterface()) {
+ SuperType = QualType(classDecl->getSuperClassType(), 0);
+ if (CurMethod->isInstanceMethod()) {
+ if (SuperType.isNull()) {
+ // The current class does not have a superclass.
+ Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
+ << CurMethod->getClassInterface()->getIdentifier();
+ return ExprError();
+ }
+ QualType T = Context.getObjCObjectPointerType(SuperType);
+
+ return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(),
+ /*BaseExpr*/nullptr,
+ SourceLocation()/*OpLoc*/,
+ &propertyName,
+ propertyNameLoc,
+ receiverNameLoc, T, true);
}
- QualType T = Context.getObjCInterfaceType(Super);
- T = Context.getObjCObjectPointerType(T);
-
- return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
- /*BaseExpr*/nullptr,
- SourceLocation()/*OpLoc*/,
- &propertyName,
- propertyNameLoc,
- receiverNameLoc, T, true);
- }
- // Otherwise, if this is a class method, try dispatching to our
- // superclass.
- IFace = CurMethod->getClassInterface()->getSuperClass();
+ // Otherwise, if this is a class method, try dispatching to our
+ // superclass.
+ IFace = CurMethod->getClassInterface()->getSuperClass();
+ }
}
}
@@ -1802,7 +1987,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
// Look for the matching setter, in case it is needed.
Selector SetterSel =
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
+ PP.getSelectorTable(),
&propertyName);
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
@@ -1819,11 +2004,11 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
return ExprError();
if (Getter || Setter) {
- if (IsSuper)
+ if (!SuperType.isNull())
return new (Context)
ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
OK_ObjCProperty, propertyNameLoc, receiverNameLoc,
- Context.getObjCInterfaceType(IFace));
+ SuperType);
return new (Context) ObjCPropertyRefExpr(
Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,
@@ -1970,8 +2155,8 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
return ExprError();
}
- ObjCInterfaceDecl *Super = Class->getSuperClass();
- if (!Super) {
+ QualType SuperTy(Class->getSuperClassType(), 0);
+ if (SuperTy.isNull()) {
// The current class does not have a superclass.
Diag(SuperLoc, diag::error_root_class_cannot_use_super)
<< Class->getIdentifier();
@@ -1986,7 +2171,6 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
if (Method->isInstanceMethod()) {
// Since we are in an instance method, this is an instance
// message to the superclass instance.
- QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,
Sel, /*Method=*/nullptr,
@@ -1996,7 +2180,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
// Since we are in a class method, this is a class message to
// the superclass.
return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
- Context.getObjCInterfaceType(Super),
+ SuperTy,
SuperLoc, Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
@@ -2437,32 +2621,41 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// of the more detailed type-checking on the receiver.
if (!Method) {
- // Handle messages to id.
- bool receiverIsId = ReceiverType->isObjCIdType();
- if (receiverIsId || ReceiverType->isBlockPointerType() ||
+ // Handle messages to id and __kindof types (where we use the
+ // global method pool).
+ // FIXME: The type bound is currently ignored by lookup in the
+ // global pool.
+ const ObjCObjectType *typeBound = nullptr;
+ bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context,
+ typeBound);
+ if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||
(Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc),
- receiverIsId);
+ receiverIsIdLike);
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc,RBracLoc),
- receiverIsId);
+ receiverIsIdLike);
if (Method) {
if (ObjCMethodDecl *BestMethod =
SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
Method = BestMethod;
- if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod()))
+ if (!AreMultipleMethodsInGlobalPool(Sel, Method,
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsIdLike)) {
DiagnoseUseOfDecl(Method, SelLoc);
+ }
}
- } else if (ReceiverType->isObjCClassType() ||
+ } else if (ReceiverType->isObjCClassOrClassKindOfType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
// We allow sending a message to a qualified Class ("Class<foo>"), which
// is ok as long as one of the protocols implements the selector (if not,
// warn).
- if (const ObjCObjectPointerType *QClassTy
- = ReceiverType->getAsObjCQualifiedClassType()) {
+ if (!ReceiverType->isObjCClassOrClassKindOfType()) {
+ const ObjCObjectPointerType *QClassTy
+ = ReceiverType->getAsObjCQualifiedClassType();
// Search protocols for class methods.
Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
if (!Method) {
@@ -2491,14 +2684,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// If not messaging 'self', look for any factory method named 'Sel'.
if (!Receiver || !isSelfExpr(Receiver)) {
Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
+ SourceRange(LBracLoc, RBracLoc));
if (!Method) {
// If no class (factory) method was found, check if an _instance_
// method of the same name exists in the root class only.
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
+ SourceRange(LBracLoc, RBracLoc));
if (Method)
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -2575,6 +2766,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
+ if (Method) {
+ if (auto BestMethod =
+ SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
+ Method = BestMethod;
+ AreMultipleMethodsInGlobalPool(Sel, Method,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ }
if (Method && !forwardClass)
Diag(SelLoc, diag::warn_maynot_respond)
<< OCIType->getInterfaceDecl()->getIdentifier()
@@ -2757,15 +2956,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
if (getLangOpts().ObjCAutoRefCount) {
- // Do not warn about IBOutlet weak property receivers being set to null
- // as this cannot asynchronously happen.
- bool WarnWeakReceiver = true;
- if (isImplicit && Method)
- if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl())
- WarnWeakReceiver = !PropertyDecl->hasAttr<IBOutletAttr>();
- if (WarnWeakReceiver)
- DiagnoseARCUseOfWeakReceiver(*this, Receiver);
-
// In ARC, annotate delegate init calls.
if (Result->getMethodFamily() == OMF_init &&
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
@@ -2796,7 +2986,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
}
-
+
+ CheckObjCCircularContainer(Result);
+
return MaybeBindToTemporary(Result);
}
@@ -2805,8 +2997,7 @@ static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {
Selector Sel = OSE->getSelector();
SourceLocation Loc = OSE->getAtLoc();
- llvm::DenseMap<Selector, SourceLocation>::iterator Pos
- = S.ReferencedSelectors.find(Sel);
+ auto Pos = S.ReferencedSelectors.find(Sel);
if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
S.ReferencedSelectors.erase(Pos);
}
@@ -3028,17 +3219,20 @@ namespace {
/// Some declaration references are okay.
ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
- // References to global constants from system headers are okay.
- // These are things like 'kCFStringTransformToLatin'. They are
- // can also be assumed to be immune to retains.
VarDecl *var = dyn_cast<VarDecl>(e->getDecl());
+ // References to global constants are okay.
if (isAnyRetainable(TargetClass) &&
isAnyRetainable(SourceClass) &&
var &&
var->getStorageClass() == SC_Extern &&
- var->getType().isConstQualified() &&
- Context.getSourceManager().isInSystemHeader(var->getLocation())) {
- return ACC_bottom;
+ var->getType().isConstQualified()) {
+
+ // In system headers, they can also be assumed to be immune to retains.
+ // These are things like 'kCFStringTransformToLatin'.
+ if (Context.getSourceManager().isInSystemHeader(var->getLocation()))
+ return ACC_bottom;
+
+ return ACC_plusZero;
}
// Nothing else.
@@ -3421,7 +3615,7 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
if ((CastClass == ExprClass) ||
- (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ (CastClass && CastClass->isSuperClassOf(ExprClass)))
return true;
if (warn)
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
@@ -3444,12 +3638,13 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
return false;
}
}
+ } else if (!castType->isObjCIdType()) {
+ S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
+ << castExpr->getType() << Parm;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
}
- S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
- << castExpr->getType() << Parm;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- if (Target)
- S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
return false;
@@ -3469,6 +3664,9 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
HadTheAttribute = true;
+ if (Parm->isStr("id"))
+ return true;
+
NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
index 32b56bc..2e327ec 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
@@ -161,11 +161,8 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
}
static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) {
- const IdentifierInfo *II = &S.getASTContext().Idents.get(Name);
- if (!II->hadMacroDefinition()) return false;
-
- MacroDirective *Macro = S.PP.getMacroDirectiveHistory(II);
- return Macro && Macro->findDirectiveAtLoc(Loc, S.getSourceManager());
+ return (bool)S.PP.getMacroDefinitionAtLoc(&S.getASTContext().Idents.get(Name),
+ Loc);
}
static std::string getScalarZeroExpressionForType(
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 2ad6754..f0f7cb9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -150,7 +150,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
Sema &S) {
// Get the length of the string as parsed.
auto *ConstantArrayTy =
- cast<ConstantArrayType>(Str->getType()->getUnqualifiedDesugaredType());
+ cast<ConstantArrayType>(Str->getType()->getAsArrayTypeUnsafe());
uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue();
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
@@ -306,7 +306,8 @@ class InitListChecker {
QualType CurrentObjectType,
InitListExpr *StructuredList,
unsigned StructuredIndex,
- SourceRange InitRange);
+ SourceRange InitRange,
+ bool IsFullyOverwritten = false);
void UpdateStructuredListElement(InitListExpr *StructuredList,
unsigned &StructuredIndex,
Expr *expr);
@@ -317,11 +318,33 @@ class InitListChecker {
SourceLocation Loc,
const InitializedEntity &Entity,
bool VerifyOnly);
+
+ // Explanation on the "FillWithNoInit" mode:
+ //
+ // Assume we have the following definitions (Case#1):
+ // struct P { char x[6][6]; } xp = { .x[1] = "bar" };
+ // struct PP { struct P lp; } l = { .lp = xp, .lp.x[1][2] = 'f' };
+ //
+ // l.lp.x[1][0..1] should not be filled with implicit initializers because the
+ // "base" initializer "xp" will provide values for them; l.lp.x[1] will be "baf".
+ //
+ // But if we have (Case#2):
+ // struct PP l = { .lp = xp, .lp.x[1] = { [2] = 'f' } };
+ //
+ // l.lp.x[1][0..1] are implicitly initialized and do not use values from the
+ // "base" initializer; l.lp.x[1] will be "\0\0f\0\0\0".
+ //
+ // To distinguish Case#1 from Case#2, and also to avoid leaving many "holes"
+ // in the InitListExpr, the "holes" in Case#1 are filled not with empty
+ // initializers but with special "NoInitExpr" place holders, which tells the
+ // CodeGen not to generate any initializers for these parts.
void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
- InitListExpr *ILE, bool &RequiresSecondPass);
+ InitListExpr *ILE, bool &RequiresSecondPass,
+ bool FillWithNoInit = false);
void FillInEmptyInitializations(const InitializedEntity &Entity,
- InitListExpr *ILE, bool &RequiresSecondPass);
+ InitListExpr *ILE, bool &RequiresSecondPass,
+ bool FillWithNoInit = false);
bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
Expr *InitExpr, FieldDecl *Field,
bool TopLevelObject);
@@ -455,12 +478,26 @@ void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity,
void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE,
- bool &RequiresSecondPass) {
+ bool &RequiresSecondPass,
+ bool FillWithNoInit) {
SourceLocation Loc = ILE->getLocEnd();
unsigned NumInits = ILE->getNumInits();
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(Field, &ParentEntity);
+
+ if (const RecordType *RType = ILE->getType()->getAs<RecordType>())
+ if (!RType->getDecl()->isUnion())
+ assert(Init < NumInits && "This ILE should have been expanded");
+
if (Init >= NumInits || !ILE->getInit(Init)) {
+ if (FillWithNoInit) {
+ Expr *Filler = new (SemaRef.Context) NoInitExpr(Field->getType());
+ if (Init < NumInits)
+ ILE->setInit(Init, Filler);
+ else
+ ILE->updateInit(SemaRef.Context, Init, Filler);
+ return;
+ }
// C++1y [dcl.init.aggr]p7:
// If there are fewer initializer-clauses in the list than there are
// members in the aggregate, then each member not explicitly initialized
@@ -516,7 +553,11 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInEmptyInitializations(MemberEntity, InnerILE,
- RequiresSecondPass);
+ RequiresSecondPass, FillWithNoInit);
+ else if (DesignatedInitUpdateExpr *InnerDIUE
+ = dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init)))
+ FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(),
+ RequiresSecondPass, /*FillWithNoInit =*/ true);
}
/// Recursively replaces NULL values within the given initializer list
@@ -525,7 +566,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
void
InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE,
- bool &RequiresSecondPass) {
+ bool &RequiresSecondPass,
+ bool FillWithNoInit) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
@@ -533,16 +575,27 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
const RecordDecl *RDecl = RType->getDecl();
if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
- Entity, ILE, RequiresSecondPass);
+ Entity, ILE, RequiresSecondPass, FillWithNoInit);
else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
for (auto *Field : RDecl->fields()) {
if (Field->hasInClassInitializer()) {
- FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass);
+ FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass,
+ FillWithNoInit);
break;
}
}
} else {
+ // The fields beyond ILE->getNumInits() are default initialized, so in
+ // order to leave them uninitialized, the ILE is expanded and the extra
+ // fields are then filled with NoInitExpr.
+ unsigned NumFields = 0;
+ for (auto *Field : RDecl->fields())
+ if (!Field->isUnnamedBitfield())
+ ++NumFields;
+ if (ILE->getNumInits() < NumFields)
+ ILE->resizeInits(SemaRef.Context, NumFields);
+
unsigned Init = 0;
for (auto *Field : RDecl->fields()) {
if (Field->isUnnamedBitfield())
@@ -551,7 +604,8 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
if (hadError)
return;
- FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
+ FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass,
+ FillWithNoInit);
if (hadError)
return;
@@ -594,13 +648,23 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
ElementEntity.setElementIndex(Init);
Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
- if (!InitExpr && !ILE->hasArrayFiller()) {
- ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
- ElementEntity,
- /*VerifyOnly*/false);
- if (ElementInit.isInvalid()) {
- hadError = true;
- return;
+ if (!InitExpr && Init < NumInits && ILE->hasArrayFiller())
+ ILE->setInit(Init, ILE->getArrayFiller());
+ else if (!InitExpr && !ILE->hasArrayFiller()) {
+ Expr *Filler = nullptr;
+
+ if (FillWithNoInit)
+ Filler = new (SemaRef.Context) NoInitExpr(ElementType);
+ else {
+ ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
+ ElementEntity,
+ /*VerifyOnly*/false);
+ if (ElementInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ Filler = ElementInit.getAs<Expr>();
}
if (hadError) {
@@ -609,29 +673,34 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
// For arrays, just set the expression used for value-initialization
// of the "holes" in the array.
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
- ILE->setArrayFiller(ElementInit.getAs<Expr>());
+ ILE->setArrayFiller(Filler);
else
- ILE->setInit(Init, ElementInit.getAs<Expr>());
+ ILE->setInit(Init, Filler);
} else {
// For arrays, just set the expression used for value-initialization
// of the rest of elements and exit.
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
- ILE->setArrayFiller(ElementInit.getAs<Expr>());
+ ILE->setArrayFiller(Filler);
return;
}
- if (!isa<ImplicitValueInitExpr>(ElementInit.get())) {
+ if (!isa<ImplicitValueInitExpr>(Filler) && !isa<NoInitExpr>(Filler)) {
// Empty initialization requires a constructor call, so
// extend the initializer list to include the constructor
// call and make a note that we'll need to take another pass
// through the initializer list.
- ILE->updateInit(SemaRef.Context, Init, ElementInit.getAs<Expr>());
+ ILE->updateInit(SemaRef.Context, Init, Filler);
RequiresSecondPass = true;
}
}
} else if (InitListExpr *InnerILE
= dyn_cast_or_null<InitListExpr>(InitExpr))
- FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+ FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass,
+ FillWithNoInit);
+ else if (DesignatedInitUpdateExpr *InnerDIUE
+ = dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr))
+ FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(),
+ RequiresSecondPass, /*FillWithNoInit =*/ true);
}
}
@@ -640,6 +709,9 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T,
bool VerifyOnly)
: SemaRef(S), VerifyOnly(VerifyOnly) {
+ // FIXME: Check that IL isn't already the semantic form of some other
+ // InitListExpr. If it is, we'd create a broken AST.
+
hadError = false;
FullyStructuredList =
@@ -751,6 +823,68 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
}
}
+/// Warn that \p Entity was of scalar type and was initialized by a
+/// single-element braced initializer list.
+static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
+ SourceRange Braces) {
+ // Don't warn during template instantiation. If the initialization was
+ // non-dependent, we warned during the initial parse; otherwise, the
+ // type might not be scalar in some uses of the template.
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+
+ unsigned DiagID = 0;
+
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
+ case InitializedEntity::EK_Result:
+ // Extra braces here are suspicious.
+ DiagID = diag::warn_braces_around_scalar_init;
+ break;
+
+ case InitializedEntity::EK_Member:
+ // Warn on aggregate initialization but not on ctor init list or
+ // default member initializer.
+ if (Entity.getParent())
+ DiagID = diag::warn_braces_around_scalar_init;
+ break;
+
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_LambdaCapture:
+ // No warning, might be direct-list-initialization.
+ // FIXME: Should we warn for copy-list-initialization in these cases?
+ break;
+
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_CompoundLiteralInit:
+ // No warning, braces are part of the syntax of the underlying construct.
+ break;
+
+ case InitializedEntity::EK_RelatedResult:
+ // No warning, we already warned when initializing the result.
+ break;
+
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
+ case InitializedEntity::EK_BlockElement:
+ llvm_unreachable("unexpected braced scalar init");
+ }
+
+ if (DiagID) {
+ S.Diag(Braces.getBegin(), DiagID)
+ << Braces
+ << FixItHint::CreateRemoval(Braces.getBegin())
+ << FixItHint::CreateRemoval(Braces.getEnd());
+ }
+}
+
+
/// Check whether the initializer \p IList (that was written with explicit
/// braces) can be used to initialize an object of type \p T.
///
@@ -826,12 +960,9 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
}
}
- if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
- !TopLevelObject)
- SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
- << IList->getSourceRange()
- << FixItHint::CreateRemoval(IList->getLocStart())
- << FixItHint::CreateRemoval(IList->getLocEnd());
+ if (!VerifyOnly && T->isScalarType() &&
+ IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0)))
+ warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
}
void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
@@ -904,19 +1035,30 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
StructuredList, StructuredIndex);
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
- if (!ElemType->isRecordType() || ElemType->isAggregateType()) {
+ if (SubInitList->getNumInits() == 1 &&
+ IsStringInit(SubInitList->getInit(0), ElemType, SemaRef.Context) ==
+ SIF_None) {
+ expr = SubInitList->getInit(0);
+ } else if (!SemaRef.getLangOpts().CPlusPlus) {
InitListExpr *InnerStructuredList
= getStructuredSubobjectInit(IList, Index, ElemType,
StructuredList, StructuredIndex,
- SubInitList->getSourceRange());
+ SubInitList->getSourceRange(), true);
CheckExplicitInitList(Entity, SubInitList, ElemType,
InnerStructuredList);
+
+ if (!hadError && !VerifyOnly) {
+ bool RequiresSecondPass = false;
+ FillInEmptyInitializations(Entity, InnerStructuredList,
+ RequiresSecondPass);
+ if (RequiresSecondPass && !hadError)
+ FillInEmptyInitializations(Entity, InnerStructuredList,
+ RequiresSecondPass);
+ }
++StructuredIndex;
++Index;
return;
}
- assert(SemaRef.getLangOpts().CPlusPlus &&
- "non-aggregate records are only possible in C++");
// C++ initialization is handled later.
} else if (isa<ImplicitValueInitExpr>(expr)) {
// This happens during template instantiation when we see an InitListExpr
@@ -929,43 +1071,24 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
return;
}
- // FIXME: Need to handle atomic aggregate types with implicit init lists.
- if (ElemType->isScalarType() || ElemType->isAtomicType())
- return CheckScalarType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
-
- assert((ElemType->isRecordType() || ElemType->isVectorType() ||
- ElemType->isArrayType()) && "Unexpected type");
-
- if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
- // arrayType can be incomplete if we're initializing a flexible
- // array member. There's nothing we can do with the completed
- // type here, though.
-
- if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
- if (!VerifyOnly) {
- CheckStringInit(expr, ElemType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
- }
- ++Index;
- return;
- }
-
- // Fall through for subaggregate initialization.
-
- } else if (SemaRef.getLangOpts().CPlusPlus) {
- // C++ [dcl.init.aggr]p12:
- // All implicit type conversions (clause 4) are considered when
- // initializing the aggregate member with an initializer from
- // an initializer-list. If the initializer can initialize a
- // member, the member is initialized. [...]
+ if (SemaRef.getLangOpts().CPlusPlus) {
+ // C++ [dcl.init.aggr]p2:
+ // Each member is copy-initialized from the corresponding
+ // initializer-clause.
// FIXME: Better EqualLoc?
InitializationKind Kind =
InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
- InitializationSequence Seq(SemaRef, Entity, Kind, expr);
+ InitializationSequence Seq(SemaRef, Entity, Kind, expr,
+ /*TopLevelOfInitList*/ true);
- if (Seq) {
+ // C++14 [dcl.init.aggr]p13:
+ // If the assignment-expression can initialize a member, the member is
+ // initialized. Otherwise [...] brace elision is assumed
+ //
+ // Brace elision is never performed if the element is not an
+ // assignment-expression.
+ if (Seq || isa<InitListExpr>(expr)) {
if (!VerifyOnly) {
ExprResult Result =
Seq.Perform(SemaRef, Entity, Kind, expr);
@@ -974,13 +1097,38 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
UpdateStructuredListElement(StructuredList, StructuredIndex,
Result.getAs<Expr>());
- }
+ } else if (!Seq)
+ hadError = true;
++Index;
return;
}
// Fall through for subaggregate initialization
+ } else if (ElemType->isScalarType() || ElemType->isAtomicType()) {
+ // FIXME: Need to handle atomic aggregate types with implicit init lists.
+ return CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ } else if (const ArrayType *arrayType =
+ SemaRef.Context.getAsArrayType(ElemType)) {
+ // arrayType can be incomplete if we're initializing a flexible
+ // array member. There's nothing we can do with the completed
+ // type here, though.
+
+ if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
+ if (!VerifyOnly) {
+ CheckStringInit(expr, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ }
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization.
+
} else {
+ assert((ElemType->isRecordType() || ElemType->isVectorType()) &&
+ "Unexpected type");
+
// C99 6.7.8p13:
//
// The initializer for a structure or union object that has
@@ -990,10 +1138,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// initial value of the object, including unnamed members, is
// that of the expression.
ExprResult ExprRes = expr;
- if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
- !VerifyOnly)
- != Sema::Incompatible) {
+ if (SemaRef.CheckSingleAssignmentConstraints(
+ ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) {
if (ExprRes.isInvalid())
hadError = true;
else {
@@ -1849,11 +1995,66 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Determine the structural initializer list that corresponds to the
// current subobject.
- StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList)
- : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
- StructuredList, StructuredIndex,
- SourceRange(D->getLocStart(),
- DIE->getLocEnd()));
+ if (IsFirstDesignator)
+ StructuredList = SyntacticToSemantic.lookup(IList);
+ else {
+ Expr *ExistingInit = StructuredIndex < StructuredList->getNumInits() ?
+ StructuredList->getInit(StructuredIndex) : nullptr;
+ if (!ExistingInit && StructuredList->hasArrayFiller())
+ ExistingInit = StructuredList->getArrayFiller();
+
+ if (!ExistingInit)
+ StructuredList =
+ getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+ StructuredList, StructuredIndex,
+ SourceRange(D->getLocStart(),
+ DIE->getLocEnd()));
+ else if (InitListExpr *Result = dyn_cast<InitListExpr>(ExistingInit))
+ StructuredList = Result;
+ else {
+ if (DesignatedInitUpdateExpr *E =
+ dyn_cast<DesignatedInitUpdateExpr>(ExistingInit))
+ StructuredList = E->getUpdater();
+ else {
+ DesignatedInitUpdateExpr *DIUE =
+ new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context,
+ D->getLocStart(), ExistingInit,
+ DIE->getLocEnd());
+ StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE);
+ StructuredList = DIUE->getUpdater();
+ }
+
+ // We need to check on source range validity because the previous
+ // initializer does not have to be an explicit initializer. e.g.,
+ //
+ // struct P { int a, b; };
+ // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 };
+ //
+ // There is an overwrite taking place because the first braced initializer
+ // list "{ .a = 2 }" already provides value for .p.b (which is zero).
+ if (ExistingInit->getSourceRange().isValid()) {
+ // We are creating an initializer list that initializes the
+ // subobjects of the current object, but there was already an
+ // initialization that completely initialized the current
+ // subobject, e.g., by a compound literal:
+ //
+ // struct X { int a, b; };
+ // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
+ //
+ // Here, xs[0].a == 0 and xs[0].b == 3, since the second,
+ // designated initializer re-initializes the whole
+ // subobject [0], overwriting previous initializers.
+ SemaRef.Diag(D->getLocStart(),
+ diag::warn_subobject_initializer_overrides)
+ << SourceRange(D->getLocStart(), DIE->getLocEnd());
+
+ SemaRef.Diag(ExistingInit->getLocStart(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << ExistingInit->getSourceRange();
+ }
+ }
+ }
assert(StructuredList && "Expected a structured initializer list");
}
@@ -2303,7 +2504,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
QualType CurrentObjectType,
InitListExpr *StructuredList,
unsigned StructuredIndex,
- SourceRange InitRange) {
+ SourceRange InitRange,
+ bool IsFullyOverwritten) {
if (VerifyOnly)
return nullptr; // No structured list in verification-only mode.
Expr *ExistingInit = nullptr;
@@ -2313,7 +2515,16 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
ExistingInit = StructuredList->getInit(StructuredIndex);
if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
- return Result;
+ // There might have already been initializers for subobjects of the current
+ // object, but a subsequent initializer list will overwrite the entirety
+ // of the current object. (See DR 253 and C99 6.7.8p21). e.g.,
+ //
+ // struct P { char x[6]; };
+ // struct P l = { .x[2] = 'x', .x = { [0] = 'f' } };
+ //
+ // The first designated initializer is ignored, and l.x is just "f".
+ if (!IsFullyOverwritten)
+ return Result;
if (ExistingInit) {
// We are creating an initializer list that initializes the
@@ -2405,13 +2616,22 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
StructuredIndex, expr)) {
// This initializer overwrites a previous initializer. Warn.
- SemaRef.Diag(expr->getLocStart(),
- diag::warn_initializer_overrides)
- << expr->getSourceRange();
- SemaRef.Diag(PrevInit->getLocStart(),
- diag::note_previous_initializer)
- << /*FIXME:has side effects=*/0
- << PrevInit->getSourceRange();
+ // We need to check on source range validity because the previous
+ // initializer does not have to be an explicit initializer.
+ // struct P { int a, b; };
+ // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 };
+ // There is an overwrite taking place because the first braced initializer
+ // list "{ .a = 2 }' already provides value for .p.b (which is zero).
+ if (PrevInit->getSourceRange().isValid()) {
+ SemaRef.Diag(expr->getLocStart(),
+ diag::warn_initializer_overrides)
+ << expr->getSourceRange();
+
+ SemaRef.Diag(PrevInit->getLocStart(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << PrevInit->getSourceRange();
+ }
}
++StructuredIndex;
@@ -3037,6 +3257,28 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
// Attempt initialization
//===----------------------------------------------------------------------===//
+/// Tries to add a zero initializer. Returns true if that worked.
+static bool
+maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence,
+ const InitializedEntity &Entity) {
+ if (Entity.getKind() != InitializedEntity::EK_Variable)
+ return false;
+
+ VarDecl *VD = cast<VarDecl>(Entity.getDecl());
+ if (VD->getInit() || VD->getLocEnd().isMacroID())
+ return false;
+
+ QualType VariableTy = VD->getType().getCanonicalType();
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
+ if (!Init.empty()) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ Sequence.SetZeroInitializationFixit(Init, Loc);
+ return true;
+ }
+ return false;
+}
+
static void MaybeProduceObjCObject(Sema &S,
InitializationSequence &Sequence,
const InitializedEntity &Entity) {
@@ -3107,15 +3349,13 @@ static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
MultiExprArg Args,
OverloadCandidateSet &CandidateSet,
- ArrayRef<NamedDecl *> Ctors,
+ DeclContext::lookup_result Ctors,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
- bool OnlyListConstructors, bool InitListSyntax) {
+ bool OnlyListConstructors, bool IsListInit) {
CandidateSet.clear();
- for (ArrayRef<NamedDecl *>::iterator
- Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
+ for (NamedDecl *D : Ctors) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
@@ -3129,19 +3369,21 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
Constructor = cast<CXXConstructorDecl>(D);
// C++11 [over.best.ics]p4:
- // However, when considering the argument of a constructor or
- // user-defined conversion function that is a candidate:
- // -- by 13.3.1.3 when invoked for the copying/moving of a temporary
- // in the second step of a class copy-initialization,
- // -- by 13.3.1.7 when passing the initializer list as a single
- // argument or when the initializer list has exactly one elementand
- // a conversion to some class X or reference to (possibly
- // cv-qualified) X is considered for the first parameter of a
- // constructor of X, or
- // -- by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases,
- // only standard conversion sequences and ellipsis conversion sequences
- // are considered.
- if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) &&
+ // ... and the constructor or user-defined conversion function is a
+ // candidate by
+ // - 13.3.1.3, when the argument is the temporary in the second step
+ // of a class copy-initialization, or
+ // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases),
+ // user-defined conversion sequences are not considered.
+ // FIXME: This breaks backward compatibility, e.g. PR12117. As a
+ // temporary fix, let's re-instate the third bullet above until
+ // there is a resolution in the standard, i.e.,
+ // - 13.3.1.7 when the initializer list has exactly one element that is
+ // itself an initializer list and a conversion to some class X or
+ // reference to (possibly cv-qualified) X is considered for the first
+ // parameter of a constructor of X.
+ if ((CopyInitializing ||
+ (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
Constructor->isCopyOrMoveConstructor())
SuppressUserConversions = true;
}
@@ -3178,16 +3420,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
-/// If InitListSyntax is true, this is list-initialization of a non-aggregate
-/// class type.
+/// \param IsListInit Is this list-initialization?
+/// \param IsInitListCopy Is this non-list-initialization resulting from a
+/// list-initialization from {x} where x is the same
+/// type as the entity?
static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args, QualType DestType,
InitializationSequence &Sequence,
- bool InitListSyntax = false) {
- assert((!InitListSyntax || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
- "InitListSyntax must come with a single initializer list argument.");
+ bool IsListInit = false,
+ bool IsInitListCopy = false) {
+ assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
+ "IsListInit must come with a single initializer list argument.");
// The type we're constructing needs to be complete.
if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
@@ -3206,29 +3451,28 @@ static void TryConstructorInitialization(Sema &S,
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax;
+ bool AllowExplicit = Kind.AllowExplicit() || IsListInit;
bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
// - Otherwise, if T is a class type, constructors are considered. The
// applicable constructors are enumerated, and the best one is chosen
// through overload resolution.
- DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl);
- // The container holding the constructors can under certain conditions
- // be changed while iterating (e.g. because of deserialization).
- // To be safe we copy the lookup results to a new container.
- SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
+ DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl);
OverloadingResult Result = OR_No_Viable_Function;
OverloadCandidateSet::iterator Best;
bool AsInitializerList = false;
- // C++11 [over.match.list]p1:
- // When objects of non-aggregate type T are list-initialized, overload
- // resolution selects the constructor in two phases:
+ // C++11 [over.match.list]p1, per DR1467:
+ // When objects of non-aggregate type T are list-initialized, such that
+ // 8.5.4 [dcl.init.list] specifies that overload resolution is performed
+ // according to the rules in this section, overload resolution selects
+ // the constructor in two phases:
+ //
// - Initially, the candidate functions are the initializer-list
// constructors of the class T and the argument list consists of the
// initializer list as a single argument.
- if (InitListSyntax) {
+ if (IsListInit) {
InitListExpr *ILE = cast<InitListExpr>(Args[0]);
AsInitializerList = true;
@@ -3239,7 +3483,7 @@ static void TryConstructorInitialization(Sema &S,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructor=*/true,
- InitListSyntax);
+ IsListInit);
// Time to unwrap the init list.
Args = MultiExprArg(ILE->getInits(), ILE->getNumInits());
@@ -3256,10 +3500,10 @@ static void TryConstructorInitialization(Sema &S,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/false,
- InitListSyntax);
+ IsListInit);
}
if (Result) {
- Sequence.SetOverloadFailure(InitListSyntax ?
+ Sequence.SetOverloadFailure(IsListInit ?
InitializationSequence::FK_ListConstructorOverloadFailed :
InitializationSequence::FK_ConstructorOverloadFailed,
Result);
@@ -3273,7 +3517,8 @@ static void TryConstructorInitialization(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Default &&
Entity.getType().isConstQualified() &&
!cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -3281,7 +3526,7 @@ static void TryConstructorInitialization(Sema &S,
// In copy-list-initialization, if an explicit constructor is chosen, the
// initializer is ill-formed.
CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
- if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+ if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
return;
}
@@ -3289,10 +3534,9 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
bool HadMultipleCandidates = (CandidateSet.size() > 1);
- Sequence.AddConstructorInitializationStep(CtorDecl,
- Best->FoundDecl.getAccess(),
- DestType, HadMultipleCandidates,
- InitListSyntax, AsInitializerList);
+ Sequence.AddConstructorInitializationStep(
+ CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates,
+ IsListInit | IsInitListCopy, AsInitializerList);
}
static bool
@@ -3350,6 +3594,11 @@ static void TryReferenceListInitialization(Sema &S,
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
}
+ // Can't reference initialize a compound literal.
+ if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) {
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+ return;
+ }
QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
@@ -3425,48 +3674,97 @@ static void TryListInitialization(Sema &S,
TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
return;
}
- if (DestType->isRecordType()) {
- if (S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
- Sequence.setIncompleteTypeFailure(DestType);
- return;
- }
- // C++11 [dcl.init.list]p3:
- // - If T is an aggregate, aggregate initialization is performed.
- if (!DestType->isAggregateType()) {
- if (S.getLangOpts().CPlusPlus11) {
- // - Otherwise, if the initializer list has no elements and T is a
- // class type with a default constructor, the object is
- // value-initialized.
- if (InitList->getNumInits() == 0) {
- CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
- if (RD->hasDefaultConstructor()) {
- TryValueInitialization(S, Entity, Kind, Sequence, InitList);
- return;
- }
+ if (DestType->isRecordType() &&
+ S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
+ Sequence.setIncompleteTypeFailure(DestType);
+ return;
+ }
+
+ // C++11 [dcl.init.list]p3, per DR1467:
+ // - If T is a class type and the initializer list has a single element of
+ // type cv U, where U is T or a class derived from T, the object is
+ // initialized from that element (by copy-initialization for
+ // copy-list-initialization, or by direct-initialization for
+ // direct-list-initialization).
+ // - Otherwise, if T is a character array and the initializer list has a
+ // single element that is an appropriately-typed string literal
+ // (8.5.2 [dcl.init.string]), initialization is performed as described
+ // in that section.
+ // - Otherwise, if T is an aggregate, [...] (continue below).
+ if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) {
+ if (DestType->isRecordType()) {
+ QualType InitType = InitList->getInit(0)->getType();
+ if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
+ S.IsDerivedFrom(InitType, DestType)) {
+ Expr *InitAsExpr = InitList->getInit(0);
+ TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
+ Sequence, /*InitListSyntax*/ false,
+ /*IsInitListCopy*/ true);
+ return;
+ }
+ }
+ if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) {
+ Expr *SubInit[1] = {InitList->getInit(0)};
+ if (!isa<VariableArrayType>(DestAT) &&
+ IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) {
+ InitializationKind SubKind =
+ Kind.getKind() == InitializationKind::IK_DirectList
+ ? InitializationKind::CreateDirect(Kind.getLocation(),
+ InitList->getLBraceLoc(),
+ InitList->getRBraceLoc())
+ : Kind;
+ Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
+ /*TopLevelOfInitList*/ true);
+
+ // TryStringLiteralInitialization() (in InitializeFrom()) will fail if
+ // the element is not an appropriately-typed string literal, in which
+ // case we should proceed as in C++11 (below).
+ if (Sequence) {
+ Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
+ return;
}
+ }
+ }
+ }
- // - Otherwise, if T is a specialization of std::initializer_list<E>,
- // an initializer_list object constructed [...]
- if (TryInitializerListConstruction(S, InitList, DestType, Sequence))
+ // C++11 [dcl.init.list]p3:
+ // - If T is an aggregate, aggregate initialization is performed.
+ if (DestType->isRecordType() && !DestType->isAggregateType()) {
+ if (S.getLangOpts().CPlusPlus11) {
+ // - Otherwise, if the initializer list has no elements and T is a
+ // class type with a default constructor, the object is
+ // value-initialized.
+ if (InitList->getNumInits() == 0) {
+ CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
+ if (RD->hasDefaultConstructor()) {
+ TryValueInitialization(S, Entity, Kind, Sequence, InitList);
return;
+ }
+ }
- // - Otherwise, if T is a class type, constructors are considered.
- Expr *InitListAsExpr = InitList;
- TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
- Sequence, /*InitListSyntax*/true);
- } else
- Sequence.SetFailed(
- InitializationSequence::FK_InitListBadDestinationType);
- return;
- }
+ // - Otherwise, if T is a specialization of std::initializer_list<E>,
+ // an initializer_list object constructed [...]
+ if (TryInitializerListConstruction(S, InitList, DestType, Sequence))
+ return;
+
+ // - Otherwise, if T is a class type, constructors are considered.
+ Expr *InitListAsExpr = InitList;
+ TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
+ Sequence, /*InitListSyntax*/ true);
+ } else
+ Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+ return;
}
+
if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&
InitList->getNumInits() == 1 &&
InitList->getInit(0)->getType()->isRecordType()) {
// - Otherwise, if the initializer list has a single element of type E
// [...references are handled above...], the object or reference is
- // initialized from that element; if a narrowing conversion is required
+ // initialized from that element (by copy-initialization for
+ // copy-list-initialization, or by direct-initialization for
+ // direct-list-initialization); if a narrowing conversion is required
// to convert the element to T, the program is ill-formed.
//
// Per core-24034, this is direct-initialization if we were performing
@@ -3543,14 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
- DeclContext::lookup_result R = S.LookupConstructors(T1RecordDecl);
- // The container holding the constructors can under certain conditions
- // be changed while iterating (e.g. because of deserialization).
- // To be safe we copy the lookup results to a new container.
- SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
- for (SmallVectorImpl<NamedDecl *>::iterator
- CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
- NamedDecl *D = *CI;
+ for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
@@ -3586,11 +3877,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = T2RecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4127,7 +4415,8 @@ static void TryDefaultInitialization(Sema &S,
// a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -4218,11 +4507,9 @@ static void TryUserDefinedConversion(Sema &S,
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = SourceRecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions =
+ SourceRecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4408,8 +4695,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
/// \brief Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
-static bool hasCompatibleArrayTypes(ASTContext &Context,
- const ArrayType *Dest,
+static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest,
const ArrayType *Source) {
// If the source and destination array types are equivalent, we're
// done.
@@ -4668,7 +4954,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
return;
}
- // Determine whether we should consider writeback conversions for
+ // Determine whether we should consider writeback conversions for
// Objective-C ARC.
bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
Entity.isParameterKind();
@@ -4802,10 +5088,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
InitializationSequence::~InitializationSequence() {
- for (SmallVectorImpl<Step>::iterator Step = Steps.begin(),
- StepEnd = Steps.end();
- Step != StepEnd; ++Step)
- Step->Destroy();
+ for (auto &S : Steps)
+ S.Destroy();
}
//===----------------------------------------------------------------------===//
@@ -5022,6 +5306,8 @@ static ExprResult CopyObject(Sema &S,
const InitializedEntity &Entity,
ExprResult CurInit,
bool IsExtraneousCopy) {
+ if (CurInit.isInvalid())
+ return CurInit;
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = nullptr;
@@ -5636,6 +5922,115 @@ static void DiagnoseNarrowingInInitList(Sema &S,
QualType EntityType,
const Expr *PostInit);
+/// Provide warnings when std::move is used on construction.
+static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
+ bool IsReturnStmt) {
+ if (!InitExpr)
+ return;
+
+ QualType DestType = InitExpr->getType();
+ if (!DestType->isRecordType())
+ return;
+
+ unsigned DiagID = 0;
+ if (IsReturnStmt) {
+ const CXXConstructExpr *CCE =
+ dyn_cast<CXXConstructExpr>(InitExpr->IgnoreParens());
+ if (!CCE || CCE->getNumArgs() != 1)
+ return;
+
+ if (!CCE->getConstructor()->isCopyOrMoveConstructor())
+ return;
+
+ InitExpr = CCE->getArg(0)->IgnoreImpCasts();
+
+ // Remove implicit temporary and constructor nodes.
+ if (const MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(InitExpr)) {
+ InitExpr = MTE->GetTemporaryExpr()->IgnoreImpCasts();
+ while (const CXXConstructExpr *CCE =
+ dyn_cast<CXXConstructExpr>(InitExpr)) {
+ if (isa<CXXTemporaryObjectExpr>(CCE))
+ return;
+ if (CCE->getNumArgs() == 0)
+ return;
+ if (CCE->getNumArgs() > 1 && !isa<CXXDefaultArgExpr>(CCE->getArg(1)))
+ return;
+ InitExpr = CCE->getArg(0);
+ }
+ InitExpr = InitExpr->IgnoreImpCasts();
+ DiagID = diag::warn_redundant_move_on_return;
+ }
+ }
+
+ // Find the std::move call and get the argument.
+ const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());
+ if (!CE || CE->getNumArgs() != 1)
+ return;
+
+ const FunctionDecl *MoveFunction = CE->getDirectCallee();
+ if (!MoveFunction || !MoveFunction->isInStdNamespace() ||
+ !MoveFunction->getIdentifier() ||
+ !MoveFunction->getIdentifier()->isStr("move"))
+ return;
+
+ const Expr *Arg = CE->getArg(0)->IgnoreImplicit();
+
+ if (IsReturnStmt) {
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts());
+ if (!DRE || DRE->refersToEnclosingVariableOrCapture())
+ return;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (!VD || !VD->hasLocalStorage())
+ return;
+
+ if (!VD->getType()->isRecordType())
+ return;
+
+ if (DiagID == 0) {
+ DiagID = S.Context.hasSameUnqualifiedType(DestType, VD->getType())
+ ? diag::warn_pessimizing_move_on_return
+ : diag::warn_redundant_move_on_return;
+ }
+ } else {
+ DiagID = diag::warn_pessimizing_move_on_initialization;
+ const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens();
+ if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType())
+ return;
+ }
+
+ S.Diag(CE->getLocStart(), DiagID);
+
+ // Get all the locations for a fix-it. Don't emit the fix-it if any location
+ // is within a macro.
+ SourceLocation CallBegin = CE->getCallee()->getLocStart();
+ if (CallBegin.isMacroID())
+ return;
+ SourceLocation RParen = CE->getRParenLoc();
+ if (RParen.isMacroID())
+ return;
+ SourceLocation LParen;
+ SourceLocation ArgLoc = Arg->getLocStart();
+
+ // Special testing for the argument location. Since the fix-it needs the
+ // location right before the argument, the argument location can be in a
+ // macro only if it is at the beginning of the macro.
+ while (ArgLoc.isMacroID() &&
+ S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
+ ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;
+ }
+
+ if (LParen.isMacroID())
+ return;
+
+ LParen = ArgLoc.getLocWithOffset(-1);
+
+ S.Diag(CE->getLocStart(), diag::note_remove_move)
+ << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen))
+ << FixItHint::CreateRemoval(SourceRange(RParen, RParen));
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -5646,6 +6041,21 @@ InitializationSequence::Perform(Sema &S,
Diagnose(S, Entity, Kind, Args);
return ExprError();
}
+ if (!ZeroInitializationFixit.empty()) {
+ unsigned DiagID = diag::err_default_init_const;
+ if (Decl *D = Entity.getDecl())
+ if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>())
+ DiagID = diag::ext_default_init_const;
+
+ // The initialization would have succeeded with this fixit. Since the fixit
+ // is on the error, we need to build a valid AST in this case, so this isn't
+ // handled in the Failed() branch above.
+ QualType DestType = Entity.getType();
+ S.Diag(Kind.getLocation(), DiagID)
+ << DestType << (bool)DestType->getAs<RecordType>()
+ << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
+ ZeroInitializationFixit);
+ }
if (getKind() == DependentSequence) {
// If the declaration is a non-dependent, incomplete array type
@@ -5820,15 +6230,6 @@ InitializationSequence::Perform(Sema &S,
&BasePath, IgnoreBaseAccess))
return ExprError();
- if (S.BasePathInvolvesVirtualBase(BasePath)) {
- QualType T = SourceType;
- if (const PointerType *Pointer = T->getAs<PointerType>())
- T = Pointer->getPointeeType();
- if (const RecordType *RecordTy = T->getAs<RecordType>())
- S.MarkVTableUsed(CurInit.get()->getLocStart(),
- cast<CXXRecordDecl>(RecordTy->getDecl()));
- }
-
ExprValueKind VK =
Step->Kind == SK_CastDerivedToBaseLValue ?
VK_LValue :
@@ -6359,6 +6760,12 @@ InitializationSequence::Perform(Sema &S,
cast<FieldDecl>(Entity.getDecl()),
CurInit.get());
+ // Check for std::move on construction.
+ if (const Expr *E = CurInit.get()) {
+ CheckMoveOnConstruction(S, E,
+ Entity.getKind() == InitializedEntity::EK_Result);
+ }
+
return CurInit;
}
@@ -6455,26 +6862,6 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
"Inconsistent init list check result.");
}
-/// Prints a fixit for adding a null initializer for |Entity|. Call this only
-/// right after emitting a diagnostic.
-static void maybeEmitZeroInitializationFixit(Sema &S,
- InitializationSequence &Sequence,
- const InitializedEntity &Entity) {
- if (Entity.getKind() != InitializedEntity::EK_Variable)
- return;
-
- VarDecl *VD = cast<VarDecl>(Entity.getDecl());
- if (VD->getInit() || VD->getLocEnd().isMacroID())
- return;
-
- QualType VariableTy = VD->getType().getCanonicalType();
- SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
- std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
-
- S.Diag(Loc, diag::note_add_initializer)
- << VD << FixItHint::CreateInsertion(Loc, Init);
-}
-
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -6622,12 +7009,19 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
- case FK_ReferenceInitDropsQualifiers:
+ case FK_ReferenceInitDropsQualifiers: {
+ QualType SourceType = Args[0]->getType();
+ QualType NonRefType = DestType.getNonReferenceType();
+ Qualifiers DroppedQualifiers =
+ SourceType.getQualifiers() - NonRefType.getQualifiers();
+
S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
- << DestType.getNonReferenceType()
- << Args[0]->getType()
+ << SourceType
+ << NonRefType
+ << DroppedQualifiers.getCVRQualifiers()
<< Args[0]->getSourceRange();
break;
+ }
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
@@ -6659,9 +7053,9 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_TooManyInitsForScalar: {
SourceRange R;
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
- R = SourceRange(InitList->getInit(0)->getLocEnd(),
- InitList->getLocEnd());
+ auto *InitList = dyn_cast<InitListExpr>(Args[0]);
+ if (InitList && InitList->getNumInits() == 1)
+ R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
else
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
@@ -6806,7 +7200,6 @@ bool InitializationSequence::Diagnose(Sema &S,
} else {
S.Diag(Kind.getLocation(), diag::err_default_init_const)
<< DestType << (bool)DestType->getAs<RecordType>();
- maybeEmitZeroInitializationFixit(S, *this, Entity);
}
break;
@@ -7262,7 +7655,6 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
EqualLoc,
AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
- Init.get();
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 90a81f4..8220641 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -818,7 +818,6 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
NewVD->markUsed(Context);
NewVD->setInit(Init);
return NewVD;
-
}
FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
@@ -837,7 +836,8 @@ FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
}
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
- Declarator &ParamInfo, Scope *CurScope) {
+ Declarator &ParamInfo,
+ Scope *CurScope) {
// Determine if we're within a context where we know that the lambda will
// be dependent, because there are template parameters in scope.
bool KnownDependent = false;
@@ -930,12 +930,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
PushDeclContext(CurScope, Method);
// Build the lambda scope.
- buildLambdaScope(LSI, Method,
- Intro.Range,
- Intro.Default, Intro.DefaultLoc,
- ExplicitParams,
- ExplicitResultType,
- !Method->isConst());
+ buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
+ ExplicitParams, ExplicitResultType, !Method->isConst());
// C++11 [expr.prim.lambda]p9:
// A lambda-expression whose smallest enclosing scope is a block scope is a
@@ -1137,7 +1133,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
bool IsInstantiation) {
- LambdaScopeInfo *LSI = getCurLambda();
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back());
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
@@ -1340,22 +1336,27 @@ static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- QualType BlockPtrTy;
- {
- FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
- ExtInfo.TypeQuals = 0;
- QualType FunctionTy = S.Context.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(), ExtInfo);
- BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
- }
+ const FunctionProtoType *Proto =
+ CallOperator->getType()->getAs<FunctionProtoType>();
+
+ // The function type inside the block pointer type is the same as the call
+ // operator with some tweaks. The calling convention is the default free
+ // function convention, and the type qualifications are lost.
+ FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo();
+ BlockEPI.ExtInfo =
+ BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention(
+ Proto->isVariadic(), /*IsCXXMethod=*/false));
+ BlockEPI.TypeQuals = 0;
+ QualType FunctionTy = S.Context.getFunctionType(
+ Proto->getReturnType(), Proto->getParamTypes(), BlockEPI);
+ QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
+
+ FunctionProtoType::ExtProtoInfo ConversionEPI(
+ S.Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true));
+ ConversionEPI.TypeQuals = Qualifiers::Const;
+ QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI);
- FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention(
- /*IsVariadic=*/false, /*IsCXXMethod=*/true));
- ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo);
-
SourceLocation Loc = IntroducerRange.getBegin();
DeclarationName Name
= S.Context.DeclarationNames.getCXXConversionFunctionName(
@@ -1374,15 +1375,131 @@ static void addBlockPointerConversion(Sema &S,
Conversion->setImplicit(true);
Class->addDecl(Conversion);
}
+
+static ExprResult performLambdaVarCaptureInitialization(
+ Sema &S, LambdaScopeInfo::Capture &Capture,
+ FieldDecl *Field,
+ SmallVectorImpl<VarDecl *> &ArrayIndexVars,
+ SmallVectorImpl<unsigned> &ArrayIndexStarts) {
+ assert(Capture.isVariableCapture() && "not a variable capture");
+
+ auto *Var = Capture.getVariable();
+ SourceLocation Loc = Capture.getLocation();
+
+ // C++11 [expr.prim.lambda]p21:
+ // When the lambda-expression is evaluated, the entities that
+ // are captured by copy are used to direct-initialize each
+ // corresponding non-static data member of the resulting closure
+ // object. (For array members, the array elements are
+ // direct-initialized in increasing subscript order.) These
+ // initializations are performed in the (unspecified) order in
+ // which the non-static data members are declared.
+
+ // C++ [expr.prim.lambda]p12:
+ // An entity captured by a lambda-expression is odr-used (3.2) in
+ // the scope containing the lambda-expression.
+ ExprResult RefResult = S.BuildDeclarationNameExpr(
+ CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
+ if (RefResult.isInvalid())
+ return ExprError();
+ Expr *Ref = RefResult.get();
+
+ QualType FieldType = Field->getType();
+
+ // When the variable has array type, create index variables for each
+ // dimension of the array. We use these index variables to subscript
+ // the source array, and other clients (e.g., CodeGen) will perform
+ // the necessary iteration with these index variables.
+ //
+ // FIXME: This is dumb. Add a proper AST representation for array
+ // copy-construction and use it here.
+ SmallVector<VarDecl *, 4> IndexVariables;
+ QualType BaseType = FieldType;
+ QualType SizeType = S.Context.getSizeType();
+ ArrayIndexStarts.push_back(ArrayIndexVars.size());
+ while (const ConstantArrayType *Array
+ = S.Context.getAsConstantArrayType(BaseType)) {
+ // Create the iteration variable for this array index.
+ IdentifierInfo *IterationVarName = nullptr;
+ {
+ SmallString<8> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "__i" << IndexVariables.size();
+ IterationVarName = &S.Context.Idents.get(OS.str());
+ }
+ VarDecl *IterationVar = VarDecl::Create(
+ S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType,
+ S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None);
+ IterationVar->setImplicit();
+ IndexVariables.push_back(IterationVar);
+ ArrayIndexVars.push_back(IterationVar);
+
+ // Create a reference to the iteration variable.
+ ExprResult IterationVarRef =
+ S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
+ assert(!IterationVarRef.isInvalid() &&
+ "Reference to invented variable cannot fail!");
+ IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get());
+ assert(!IterationVarRef.isInvalid() &&
+ "Conversion of invented variable cannot fail!");
+
+ // Subscript the array with this iteration variable.
+ ExprResult Subscript =
+ S.CreateBuiltinArraySubscriptExpr(Ref, Loc, IterationVarRef.get(), Loc);
+ if (Subscript.isInvalid())
+ return ExprError();
+
+ Ref = Subscript.get();
+ BaseType = Array->getElementType();
+ }
+
+ // Construct the entity that we will be initializing. For an array, this
+ // will be first element in the array, which may require several levels
+ // of array-subscript entities.
+ SmallVector<InitializedEntity, 4> Entities;
+ Entities.reserve(1 + IndexVariables.size());
+ Entities.push_back(InitializedEntity::InitializeLambdaCapture(
+ Var->getIdentifier(), FieldType, Loc));
+ for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+ Entities.push_back(
+ InitializedEntity::InitializeElement(S.Context, 0, Entities.back()));
+
+ InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc);
+ InitializationSequence Init(S, Entities.back(), InitKind, Ref);
+ return Init.Perform(S, Entities.back(), InitKind, Ref);
+}
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
- Scope *CurScope,
- bool IsInstantiation) {
+ Scope *CurScope) {
+ LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
+ ActOnFinishFunctionBody(LSI.CallOperator, Body);
+ return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI);
+}
+
+static LambdaCaptureDefault
+mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
+ switch (ICS) {
+ case CapturingScopeInfo::ImpCap_None:
+ return LCD_None;
+ case CapturingScopeInfo::ImpCap_LambdaByval:
+ return LCD_ByCopy;
+ case CapturingScopeInfo::ImpCap_CapturedRegion:
+ case CapturingScopeInfo::ImpCap_LambdaByref:
+ return LCD_ByRef;
+ case CapturingScopeInfo::ImpCap_Block:
+ llvm_unreachable("block capture in lambda");
+ }
+ llvm_unreachable("Unknown implicit capture style");
+}
+
+ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+ LambdaScopeInfo *LSI) {
// Collect information from the lambda scope.
SmallVector<LambdaCapture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
- LambdaCaptureDefault CaptureDefault;
- SourceLocation CaptureDefaultLoc;
+ SourceLocation CaptureDefaultLoc = LSI->CaptureDefaultLoc;
+ LambdaCaptureDefault CaptureDefault =
+ mapImplicitCaptureStyle(LSI->ImpCaptureStyle);
CXXRecordDecl *Class;
CXXMethodDecl *CallOperator;
SourceRange IntroducerRange;
@@ -1393,7 +1510,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
SmallVector<VarDecl *, 4> ArrayIndexVars;
SmallVector<unsigned, 4> ArrayIndexStarts;
{
- LambdaScopeInfo *LSI = getCurLambda();
CallOperator = LSI->CallOperator;
Class = LSI->Lambda;
IntroducerRange = LSI->IntroducerRange;
@@ -1401,11 +1517,21 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
ExplicitResultType = !LSI->HasImplicitReturnType;
LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
- ArrayIndexVars.swap(LSI->ArrayIndexVars);
- ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
+ CallOperator->setLexicalDeclContext(Class);
+ Decl *TemplateOrNonTemplateCallOperatorDecl =
+ CallOperator->getDescribedFunctionTemplate()
+ ? CallOperator->getDescribedFunctionTemplate()
+ : cast<Decl>(CallOperator);
+
+ TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
+ Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
+
+ PopExpressionEvaluationContext();
+
// Translate captures.
- for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
+ auto CurField = Class->field_begin();
+ for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
LambdaScopeInfo::Capture From = LSI->Captures[I];
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
@@ -1417,83 +1543,33 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
getCurrentThisType(),
/*isImplicit=*/true));
+ ArrayIndexStarts.push_back(ArrayIndexVars.size());
continue;
}
if (From.isVLATypeCapture()) {
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType));
CaptureInits.push_back(nullptr);
+ ArrayIndexStarts.push_back(ArrayIndexVars.size());
continue;
}
VarDecl *Var = From.getVariable();
- LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
+ LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef;
Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind,
Var, From.getEllipsisLoc()));
- CaptureInits.push_back(From.getInitExpr());
- }
-
- switch (LSI->ImpCaptureStyle) {
- case CapturingScopeInfo::ImpCap_None:
- CaptureDefault = LCD_None;
- break;
-
- case CapturingScopeInfo::ImpCap_LambdaByval:
- CaptureDefault = LCD_ByCopy;
- break;
-
- case CapturingScopeInfo::ImpCap_CapturedRegion:
- case CapturingScopeInfo::ImpCap_LambdaByref:
- CaptureDefault = LCD_ByRef;
- break;
-
- case CapturingScopeInfo::ImpCap_Block:
- llvm_unreachable("block capture in lambda");
- break;
- }
- CaptureDefaultLoc = LSI->CaptureDefaultLoc;
-
- // C++11 [expr.prim.lambda]p4:
- // If a lambda-expression does not include a
- // trailing-return-type, it is as if the trailing-return-type
- // denotes the following type:
- //
- // Skip for C++1y return type deduction semantics which uses
- // different machinery.
- // FIXME: Refactor and Merge the return type deduction machinery.
- // FIXME: Assumes current resolution to core issue 975.
- if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus14) {
- deduceClosureReturnType(*LSI);
-
- // - if there are no return statements in the
- // compound-statement, or all return statements return
- // either an expression of type void or no expression or
- // braced-init-list, the type void;
- if (LSI->ReturnType.isNull()) {
- LSI->ReturnType = Context.VoidTy;
+ Expr *Init = From.getInitExpr();
+ if (!Init) {
+ auto InitResult = performLambdaVarCaptureInitialization(
+ *this, From, *CurField, ArrayIndexVars, ArrayIndexStarts);
+ if (InitResult.isInvalid())
+ return ExprError();
+ Init = InitResult.get();
+ } else {
+ ArrayIndexStarts.push_back(ArrayIndexVars.size());
}
-
- // Create a function type with the inferred return type.
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- QualType FunctionTy = Context.getFunctionType(
- LSI->ReturnType, Proto->getParamTypes(), Proto->getExtProtoInfo());
- CallOperator->setType(FunctionTy);
+ CaptureInits.push_back(Init);
}
- // C++ [expr.prim.lambda]p7:
- // The lambda-expression's compound-statement yields the
- // function-body (8.4) of the function call operator [...].
- ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
- CallOperator->setLexicalDeclContext(Class);
- Decl *TemplateOrNonTemplateCallOperatorDecl =
- CallOperator->getDescribedFunctionTemplate()
- ? CallOperator->getDescribedFunctionTemplate()
- : cast<Decl>(CallOperator);
-
- TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
- Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
-
- PopExpressionEvaluationContext();
// C++11 [expr.prim.lambda]p6:
// The closure type for a lambda-expression with no lambda-capture
@@ -1529,7 +1605,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
- ArrayIndexStarts, Body->getLocEnd(),
+ ArrayIndexStarts, EndLoc,
ContainsUnexpandedParameterPack);
if (!CurContext->isDependentContext()) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index ad06872..3fd1f21 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -23,7 +24,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Overload.h"
@@ -194,10 +197,11 @@ namespace {
const_iterator begin() const { return list.begin(); }
const_iterator end() const { return list.end(); }
- std::pair<const_iterator,const_iterator>
+ llvm::iterator_range<const_iterator>
getNamespacesFor(DeclContext *DC) const {
- return std::equal_range(begin(), end(), DC->getPrimaryContext(),
- UnqualUsingEntry::Comparator());
+ return llvm::make_range(std::equal_range(begin(), end(),
+ DC->getPrimaryContext(),
+ UnqualUsingEntry::Comparator()));
}
};
}
@@ -413,6 +417,10 @@ void LookupResult::resolveKind() {
if (!Unique.insert(D).second) {
// If it's not unique, pull something off the back (and
// continue at this index).
+ // FIXME: This is wrong. We need to take the more recent declaration in
+ // order to get the right type, default arguments, etc. We also need to
+ // prefer visible declarations to hidden ones (for redeclaration lookup
+ // in modules builds).
Decls[I] = Decls[--N];
continue;
}
@@ -670,8 +678,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
// Perform lookup into this declaration context.
- DeclContext::lookup_const_result DR = DC->lookup(R.getLookupName());
- for (DeclContext::lookup_const_iterator I = DR.begin(), E = DR.end(); I != E;
+ DeclContext::lookup_result DR = DC->lookup(R.getLookupName());
+ for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E;
++I) {
NamedDecl *D = *I;
if ((D = R.getAcceptableDecl(D))) {
@@ -765,11 +773,8 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
// Perform direct name lookup into the namespaces nominated by the
// using directives whose common ancestor is this namespace.
- UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- std::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
-
- for (; UI != UEnd; ++UI)
- if (LookupDirect(S, R, UI->getNominatedNamespace()))
+ for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(NS))
+ if (LookupDirect(S, R, UUE.getNominatedNamespace()))
Found = true;
R.resolveKind();
@@ -1167,8 +1172,77 @@ static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) {
return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom();
}
+Module *Sema::getOwningModule(Decl *Entity) {
+ // If it's imported, grab its owning module.
+ Module *M = Entity->getImportedOwningModule();
+ if (M || !isa<NamedDecl>(Entity) || !cast<NamedDecl>(Entity)->isHidden())
+ return M;
+ assert(!Entity->isFromASTFile() &&
+ "hidden entity from AST file has no owning module");
+
+ if (!getLangOpts().ModulesLocalVisibility) {
+ // If we're not tracking visibility locally, the only way a declaration
+ // can be hidden and local is if it's hidden because it's parent is (for
+ // instance, maybe this is a lazily-declared special member of an imported
+ // class).
+ auto *Parent = cast<NamedDecl>(Entity->getDeclContext());
+ assert(Parent->isHidden() && "unexpectedly hidden decl");
+ return getOwningModule(Parent);
+ }
+
+ // It's local and hidden; grab or compute its owning module.
+ M = Entity->getLocalOwningModule();
+ if (M)
+ return M;
+
+ if (auto *Containing =
+ PP.getModuleContainingLocation(Entity->getLocation())) {
+ M = Containing;
+ } else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) {
+ // Don't bother tracking visibility for invalid declarations with broken
+ // locations.
+ cast<NamedDecl>(Entity)->setHidden(false);
+ } else {
+ // We need to assign a module to an entity that exists outside of any
+ // module, so that we can hide it from modules that we textually enter.
+ // Invent a fake module for all such entities.
+ if (!CachedFakeTopLevelModule) {
+ CachedFakeTopLevelModule =
+ PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule(
+ "<top-level>", nullptr, false, false).first;
+
+ auto &SrcMgr = PP.getSourceManager();
+ SourceLocation StartLoc =
+ SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID());
+ auto &TopLevel =
+ VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0];
+ TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc);
+ }
+
+ M = CachedFakeTopLevelModule;
+ }
+
+ if (M)
+ Entity->setLocalOwningModule(M);
+ return M;
+}
+
+void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) {
+ if (auto *M = PP.getModuleContainingLocation(Loc))
+ Context.mergeDefinitionIntoModule(ND, M);
+ else
+ // We're not building a module; just make the definition visible.
+ ND->setHidden(false);
+
+ // If ND is a template declaration, make the template parameters
+ // visible too. They're not (necessarily) within a mergeable DeclContext.
+ if (auto *TD = dyn_cast<TemplateDecl>(ND))
+ for (auto *Param : *TD->getTemplateParameters())
+ makeMergedDefinitionVisible(Param, Loc);
+}
+
/// \brief Find the module in which the given declaration was defined.
-static Module *getDefiningModule(Decl *Entity) {
+static Module *getDefiningModule(Sema &S, Decl *Entity) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) {
// If this function was instantiated from a template, the defining module is
// the module containing the pattern.
@@ -1190,15 +1264,16 @@ static Module *getDefiningModule(Decl *Entity) {
// from a template.
DeclContext *Context = Entity->getDeclContext();
if (Context->isFileContext())
- return Entity->getOwningModule();
- return getDefiningModule(cast<Decl>(Context));
+ return S.getOwningModule(Entity);
+ return getDefiningModule(S, cast<Decl>(Context));
}
llvm::DenseSet<Module*> &Sema::getLookupModules() {
unsigned N = ActiveTemplateInstantiations.size();
for (unsigned I = ActiveTemplateInstantiationLookupModules.size();
I != N; ++I) {
- Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity);
+ Module *M =
+ getDefiningModule(*this, ActiveTemplateInstantiations[I].Entity);
if (M && !LookupModulesCache.insert(M).second)
M = nullptr;
ActiveTemplateInstantiationLookupModules.push_back(M);
@@ -1206,6 +1281,48 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
return LookupModulesCache;
}
+bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) {
+ for (Module *Merged : Context.getModulesWithMergedDefinition(Def))
+ if (isModuleVisible(Merged))
+ return true;
+ return false;
+}
+
+template<typename ParmDecl>
+static bool
+hasVisibleDefaultArgument(Sema &S, const ParmDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules) {
+ if (!D->hasDefaultArgument())
+ return false;
+
+ while (D) {
+ auto &DefaultArg = D->getDefaultArgStorage();
+ if (!DefaultArg.isInherited() && S.isVisible(D))
+ return true;
+
+ if (!DefaultArg.isInherited() && Modules) {
+ auto *NonConstD = const_cast<ParmDecl*>(D);
+ Modules->push_back(S.getOwningModule(NonConstD));
+ const auto &Merged = S.Context.getModulesWithMergedDefinition(NonConstD);
+ Modules->insert(Modules->end(), Merged.begin(), Merged.end());
+ }
+
+ // If there was a previous default argument, maybe its parameter is visible.
+ D = DefaultArg.getInheritedFrom();
+ }
+ return false;
+}
+
+bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules) {
+ if (auto *P = dyn_cast<TemplateTypeParmDecl>(D))
+ return ::hasVisibleDefaultArgument(*this, P, Modules);
+ if (auto *P = dyn_cast<NonTypeTemplateParmDecl>(D))
+ return ::hasVisibleDefaultArgument(*this, P, Modules);
+ return ::hasVisibleDefaultArgument(*this, cast<TemplateTemplateParmDecl>(D),
+ Modules);
+}
+
/// \brief Determine whether a declaration is visible to name lookup.
///
/// This routine determines whether the declaration D is visible in the current
@@ -1215,10 +1332,48 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
/// path (by instantiating a template, you allow it to see the declarations that
/// your module can see, including those later on in your module).
bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
- assert(D->isHidden() && !SemaRef.ActiveTemplateInstantiations.empty() &&
- "should not call this: not in slow case");
- Module *DeclModule = D->getOwningModule();
- assert(DeclModule && "hidden decl not from a module");
+ assert(D->isHidden() && "should not call this: not in slow case");
+ Module *DeclModule = SemaRef.getOwningModule(D);
+ if (!DeclModule) {
+ // getOwningModule() may have decided the declaration should not be hidden.
+ assert(!D->isHidden() && "hidden decl not from a module");
+ return true;
+ }
+
+ // If the owning module is visible, and the decl is not module private,
+ // then the decl is visible too. (Module private is ignored within the same
+ // top-level module.)
+ if (!D->isFromASTFile() || !D->isModulePrivate()) {
+ if (SemaRef.isModuleVisible(DeclModule))
+ return true;
+ // Also check merged definitions.
+ if (SemaRef.getLangOpts().ModulesLocalVisibility &&
+ SemaRef.hasVisibleMergedDefinition(D))
+ return true;
+ }
+
+ // If this declaration is not at namespace scope nor module-private,
+ // then it is visible if its lexical parent has a visible definition.
+ DeclContext *DC = D->getLexicalDeclContext();
+ if (!D->isModulePrivate() &&
+ DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) {
+ // For a parameter, check whether our current template declaration's
+ // lexical context is visible, not whether there's some other visible
+ // definition of it, because parameters aren't "within" the definition.
+ if ((D->isTemplateParameter() || isa<ParmVarDecl>(D))
+ ? isVisible(SemaRef, cast<NamedDecl>(DC))
+ : SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) {
+ if (SemaRef.ActiveTemplateInstantiations.empty() &&
+ // FIXME: Do something better in this case.
+ !SemaRef.getLangOpts().ModulesLocalVisibility) {
+ // Cache the fact that this declaration is implicitly visible because
+ // its parent has a visible definition.
+ D->setHidden(false);
+ }
+ return true;
+ }
+ return false;
+ }
// Find the extra places where we need to look.
llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules();
@@ -1243,6 +1398,10 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
return false;
}
+bool Sema::isVisibleSlow(const NamedDecl *D) {
+ return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D));
+}
+
/// \brief Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
@@ -1256,6 +1415,9 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
for (auto RD : D->redecls()) {
if (auto ND = dyn_cast<NamedDecl>(RD)) {
+ // FIXME: This is wrong in the case where the previous declaration is not
+ // visible in the same scope as D. This needs to be done much more
+ // carefully.
if (LookupResult::isVisible(SemaRef, ND))
return ND;
}
@@ -2885,6 +3047,9 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D))
continue;
+ if (!isVisible(D) && !(D = findAcceptableDecl(*this, D)))
+ continue;
+
Result.insert(D);
}
}
@@ -2953,7 +3118,7 @@ class ShadowContextRAII {
public:
ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) {
- Visible.ShadowMaps.push_back(ShadowMap());
+ Visible.ShadowMaps.emplace_back();
}
~ShadowContextRAII() {
@@ -3016,17 +3181,45 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ // Outside C++, lookup results for the TU live on identifiers.
+ if (isa<TranslationUnitDecl>(Ctx) &&
+ !Result.getSema().getLangOpts().CPlusPlus) {
+ auto &S = Result.getSema();
+ auto &Idents = S.Context.Idents;
+
+ // Ensure all external identifiers are in the identifier table.
+ if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
+ for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
+ Idents.get(Name);
+ }
+
+ // Walk all lookup results in the TU for each identifier.
+ for (const auto &Ident : Idents) {
+ for (auto I = S.IdResolver.begin(Ident.getValue()),
+ E = S.IdResolver.end();
+ I != E; ++I) {
+ if (S.IdResolver.isDeclInScope(*I, Ctx)) {
+ if (NamedDecl *ND = Result.getAcceptableDecl(*I)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
- for (const auto &R : Ctx->lookups()) {
- for (auto *I : R) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) {
- if ((ND = Result.getAcceptableDecl(ND))) {
- Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
- Visited.add(ND);
- }
+ for (DeclContextLookupResult R : Ctx->lookups()) {
+ for (auto *D : R) {
+ if (auto *ND = Result.getAcceptableDecl(D)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
}
}
}
@@ -3209,10 +3402,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
if (Entity) {
// Lookup visible declarations in any namespaces found by using
// directives.
- UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- std::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
- for (; UI != UEnd; ++UI)
- LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
+ for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity))
+ LookupVisibleDecls(const_cast<DeclContext *>(UUE.getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false,
/*InBaseClass=*/false, Consumer, Visited);
}
@@ -3682,8 +3873,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec)
- : Context(Context), CurContextChain(buildContextChain(CurContext)),
- isSorted(false) {
+ : Context(Context), CurContextChain(buildContextChain(CurContext)) {
if (NestedNameSpecifier *NNS =
CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) {
llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
@@ -3702,7 +3892,6 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
}
// Add the global context as a NestedNameSpecifier
- Distances.insert(1);
SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()),
NestedNameSpecifier::GlobalSpecifier(Context), 1};
DistanceMap[1].push_back(SI);
@@ -3722,22 +3911,6 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain(
return Chain;
}
-void TypoCorrectionConsumer::NamespaceSpecifierSet::sortNamespaces() {
- SmallVector<unsigned, 4> sortedDistances;
- sortedDistances.append(Distances.begin(), Distances.end());
-
- if (sortedDistances.size() > 1)
- std::sort(sortedDistances.begin(), sortedDistances.end());
-
- Specifiers.clear();
- for (auto D : sortedDistances) {
- SpecifierInfoList &SpecList = DistanceMap[D];
- Specifiers.append(SpecList.begin(), SpecList.end());
- }
-
- isSorted = true;
-}
-
unsigned
TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
DeclContextList &DeclChain, NestedNameSpecifier *&NNS) {
@@ -3818,8 +3991,6 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
llvm::makeArrayRef(NewNameSpecifierIdentifiers));
}
- isSorted = false;
- Distances.insert(NumSpecifiers);
SpecifierInfo SI = {Ctx, NNS, NumSpecifiers};
DistanceMap[NumSpecifiers].push_back(SI);
}
@@ -4294,7 +4465,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Record the failure's location if needed and return an empty correction. If
// this was an unqualified lookup and we believe the callback object did not
// filter out possible corrections, also cache the failure for the typo.
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
}
/// \brief Try to "correct" a typo in the source code by finding
@@ -4347,9 +4518,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
TypoCorrection Empty;
auto Consumer = makeTypoCorrectionConsumer(
TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
- EnteringContext, OPT,
- /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
- getLangOpts().ModulesSearchAll);
+ EnteringContext, OPT, Mode == CTK_ErrorRecovery);
if (!Consumer || Consumer->empty())
return nullptr;
@@ -4491,22 +4660,92 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
/// Find which declaration we should import to provide the definition of
/// the given declaration.
-static const NamedDecl *getDefinitionToImport(const NamedDecl *D) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+static NamedDecl *getDefinitionToImport(NamedDecl *D) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->isDefined(FD) ? FD : nullptr;
- if (const TagDecl *TD = dyn_cast<TagDecl>(D))
+ return FD->isDefined(FD) ? const_cast<FunctionDecl*>(FD) : nullptr;
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
- if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
return ID->getDefinition();
- if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
+ if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
return PD->getDefinition();
- if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
return getDefinitionToImport(TD->getTemplatedDecl());
return nullptr;
}
+void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+ bool NeedDefinition, bool Recover) {
+ assert(!isVisible(Decl) && "missing import for non-hidden decl?");
+
+ // Suggest importing a module providing the definition of this entity, if
+ // possible.
+ NamedDecl *Def = getDefinitionToImport(Decl);
+ if (!Def)
+ Def = Decl;
+
+ // FIXME: Add a Fix-It that imports the corresponding module or includes
+ // the header.
+ Module *Owner = getOwningModule(Decl);
+ assert(Owner && "definition of hidden declaration is not in a module");
+
+ llvm::SmallVector<Module*, 8> OwningModules;
+ OwningModules.push_back(Owner);
+ auto Merged = Context.getModulesWithMergedDefinition(Decl);
+ OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end());
+
+ diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules,
+ NeedDefinition ? MissingImportKind::Definition
+ : MissingImportKind::Declaration,
+ Recover);
+}
+
+void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
+ SourceLocation DeclLoc,
+ ArrayRef<Module *> Modules,
+ MissingImportKind MIK, bool Recover) {
+ assert(!Modules.empty());
+
+ if (Modules.size() > 1) {
+ std::string ModuleList;
+ unsigned N = 0;
+ for (Module *M : Modules) {
+ ModuleList += "\n ";
+ if (++N == 5 && N != Modules.size()) {
+ ModuleList += "[...]";
+ break;
+ }
+ ModuleList += M->getFullModuleName();
+ }
+
+ Diag(UseLoc, diag::err_module_unimported_use_multiple)
+ << (int)MIK << Decl << ModuleList;
+ } else {
+ Diag(UseLoc, diag::err_module_unimported_use)
+ << (int)MIK << Decl << Modules[0]->getFullModuleName();
+ }
+
+ unsigned DiagID;
+ switch (MIK) {
+ case MissingImportKind::Declaration:
+ DiagID = diag::note_previous_declaration;
+ break;
+ case MissingImportKind::Definition:
+ DiagID = diag::note_previous_definition;
+ break;
+ case MissingImportKind::DefaultArgument:
+ DiagID = diag::note_default_argument_declared_here;
+ break;
+ }
+ Diag(DeclLoc, DiagID);
+
+ // Try to recover by implicitly importing this module.
+ if (Recover)
+ createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]);
+}
+
/// \brief Diagnose a successfully-corrected typo. Separated from the correction
/// itself to allow external validation of the result, etc.
///
@@ -4533,23 +4772,8 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
NamedDecl *Decl = Correction.getCorrectionDecl();
assert(Decl && "import required but no declaration to import");
- // Suggest importing a module providing the definition of this entity, if
- // possible.
- const NamedDecl *Def = getDefinitionToImport(Decl);
- if (!Def)
- Def = Decl;
- Module *Owner = Def->getOwningModule();
- assert(Owner && "definition of hidden declaration is not in a module");
-
- Diag(Correction.getCorrectionRange().getBegin(),
- diag::err_module_private_declaration)
- << Def << Owner->getFullModuleName();
- Diag(Def->getLocation(), diag::note_previous_declaration);
-
- // Recover by implicitly importing this module.
- if (ErrorRecovery)
- createImplicitModuleImportForErrorRecovery(
- Correction.getCorrectionRange().getBegin(), Owner);
+ diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl,
+ /*NeedDefinition*/ false, ErrorRecovery);
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index 72b6020..f139c83 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
@@ -102,15 +103,6 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
<< propertyLifetime;
}
-static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
- if ((S.getLangOpts().getGC() != LangOptions::NonGC &&
- T.isObjCGCWeak()) ||
- (S.getLangOpts().ObjCAutoRefCount &&
- T.getObjCLifetime() == Qualifiers::OCL_Weak))
- return ObjCDeclSpec::DQ_PR_weak;
- return 0;
-}
-
/// \brief Check this Objective-C property against a property declared in the
/// given protocol.
static void
@@ -145,10 +137,10 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC) {
unsigned Attributes = ODS.getPropertyAttributes();
+ FD.D.setObjCWeakProperty((Attributes & ObjCDeclSpec::DQ_PR_weak) != 0);
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
QualType T = TSI->getType();
- Attributes |= deduceWeakPropertyFromType(*this, T);
-
+ Attributes |= deduceWeakPropertyFromType(T);
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
// default is readwrite!
!(Attributes & ObjCDeclSpec::DQ_PR_readonly));
@@ -172,7 +164,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
isAssign, isReadWrite,
Attributes,
ODS.getPropertyAttributes(),
- isOverridingProperty, TSI,
+ isOverridingProperty, T, TSI,
MethodImplKind);
if (!Res)
return nullptr;
@@ -183,7 +175,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
GetterSel, SetterSel, isAssign, isReadWrite,
Attributes, ODS.getPropertyAttributes(),
- TSI, MethodImplKind);
+ T, TSI, MethodImplKind);
if (lexicalDC)
Res->setLexicalDeclContext(lexicalDC);
}
@@ -321,7 +313,8 @@ Sema::HandlePropertyInClassExtension(Scope *S,
const unsigned Attributes,
const unsigned AttributesAsWritten,
bool *isOverridingProperty,
- TypeSourceInfo *T,
+ QualType T,
+ TypeSourceInfo *TSI,
tok::ObjCKeywordKind MethodImplKind) {
ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);
// Diagnose if this property is already in continuation class.
@@ -347,7 +340,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
// FIXME. We should really be using CreatePropertyDecl for this.
ObjCPropertyDecl *PDecl =
ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
- PropertyId, AtLoc, LParenLoc, T);
+ PropertyId, AtLoc, LParenLoc, T, TSI);
PDecl->setPropertyAttributesAsWritten(
makePropertyAttributesAsWritten(AttributesAsWritten));
if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
@@ -358,6 +351,11 @@ Sema::HandlePropertyInClassExtension(Scope *S,
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
+ if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+ if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
+
// Set setter/getter selector name. Needed later.
PDecl->setGetterName(GetterSel);
PDecl->setSetterName(SetterSel);
@@ -382,7 +380,8 @@ Sema::HandlePropertyInClassExtension(Scope *S,
ObjCPropertyDecl *PrimaryPDecl =
CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
FD, GetterSel, SetterSel, isAssign, isReadWrite,
- Attributes,AttributesAsWritten, T, MethodImplKind, DC);
+ Attributes,AttributesAsWritten, T, TSI, MethodImplKind,
+ DC);
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
@@ -406,9 +405,11 @@ Sema::HandlePropertyInClassExtension(Scope *S,
// this conversion is safe only because the wider type is for a 'readonly'
// property in primary class and 'narrowed' type for a 'readwrite' property
// in continuation class.
- if (!isa<ObjCObjectPointerType>(PIDecl->getType()) ||
- !isa<ObjCObjectPointerType>(PDecl->getType()) ||
- (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(),
+ QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType());
+ QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType());
+ if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) ||
+ !isa<ObjCObjectPointerType>(ClassExtPropertyT) ||
+ (!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT,
ConvertedType, IncompatibleObjC))
|| IncompatibleObjC) {
Diag(AtLoc,
@@ -424,7 +425,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
- PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
+ PIkind |= deduceWeakPropertyFromType(PIDecl->getType());
unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
@@ -528,11 +529,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
const bool isReadWrite,
const unsigned Attributes,
const unsigned AttributesAsWritten,
+ QualType T,
TypeSourceInfo *TInfo,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC){
IdentifierInfo *PropertyId = FD.D.getIdentifier();
- QualType T = TInfo->getType();
// Issue a warning if property is 'assign' as default and its object, which is
// gc'able conforms to NSCopying protocol
@@ -561,7 +562,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
DeclContext *DC = cast<DeclContext>(CDecl);
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
- PropertyId, AtLoc, LParenLoc, TInfo);
+ PropertyId, AtLoc,
+ LParenLoc, T, TInfo);
if (ObjCPropertyDecl *prevDecl =
ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
@@ -636,6 +638,12 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
else if (MethodImplKind == tok::objc_optional)
PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
+ if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
+
return PDecl;
}
@@ -1149,7 +1157,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
CK_LValueToRValue, SelfExpr, nullptr,
VK_RValue);
Expr *IvarRefExpr =
- new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ new (Context) ObjCIvarRefExpr(Ivar,
+ Ivar->getUsageType(SelfDecl->getType()),
+ PropertyDiagLoc,
Ivar->getLocation(),
LoadSelfExpr, true, true);
ExprResult Res = PerformCopyInitialization(
@@ -1199,7 +1209,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
CK_LValueToRValue, SelfExpr, nullptr,
VK_RValue);
Expr *lhs =
- new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ new (Context) ObjCIvarRefExpr(Ivar,
+ Ivar->getUsageType(SelfDecl->getType()),
+ PropertyDiagLoc,
Ivar->getLocation(),
LoadSelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
@@ -1750,6 +1762,33 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
}
+void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
+ for (const auto *propertyImpl : impDecl->property_impls()) {
+ const auto *property = propertyImpl->getPropertyDecl();
+
+ // Warn about null_resettable properties with synthesized setters,
+ // because the setter won't properly handle nil.
+ if (propertyImpl->getPropertyImplementation()
+ == ObjCPropertyImplDecl::Synthesize &&
+ (property->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_null_resettable) &&
+ property->getGetterMethodDecl() &&
+ property->getSetterMethodDecl()) {
+ auto *getterMethod = property->getGetterMethodDecl();
+ auto *setterMethod = property->getSetterMethodDecl();
+ if (!impDecl->getInstanceMethod(setterMethod->getSelector()) &&
+ !impDecl->getInstanceMethod(getterMethod->getSelector())) {
+ SourceLocation loc = propertyImpl->getLocation();
+ if (loc.isInvalid())
+ loc = impDecl->getLocStart();
+
+ Diag(loc, diag::warn_null_resettable_setter)
+ << setterMethod->getSelector() << property->getDeclName();
+ }
+ }
+ }
+}
+
void
Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl) {
@@ -1854,6 +1893,39 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
else
Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
+
+ // Look for a getter explicitly declared alongside the property.
+ // If we find one, use its location for the note.
+ SourceLocation noteLoc = PD->getLocation();
+ SourceLocation fixItLoc;
+ for (auto *getterRedecl : method->redecls()) {
+ if (getterRedecl->isImplicit())
+ continue;
+ if (getterRedecl->getDeclContext() != PD->getDeclContext())
+ continue;
+ noteLoc = getterRedecl->getLocation();
+ fixItLoc = getterRedecl->getLocEnd();
+ }
+
+ Preprocessor &PP = getPreprocessor();
+ TokenValue tokens[] = {
+ tok::kw___attribute, tok::l_paren, tok::l_paren,
+ PP.getIdentifierInfo("objc_method_family"), tok::l_paren,
+ PP.getIdentifierInfo("none"), tok::r_paren,
+ tok::r_paren, tok::r_paren
+ };
+ StringRef spelling = "__attribute__((objc_method_family(none)))";
+ StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens);
+ if (!macroName.empty())
+ spelling = macroName;
+
+ auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family)
+ << method->getDeclName() << spelling;
+ if (fixItLoc.isValid()) {
+ SmallString<64> fixItText(" ");
+ fixItText += spelling;
+ noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText);
+ }
}
}
}
@@ -1952,9 +2024,21 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
redeclaredProperty->getLocation() :
property->getLocation();
+ // If the property is null_resettable, the getter returns nonnull.
+ QualType resultTy = property->getType();
+ if (property->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_null_resettable) {
+ QualType modifiedTy = resultTy;
+ if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
+ if (*nullability == NullabilityKind::Unspecified)
+ resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
+ modifiedTy, modifiedTy);
+ }
+ }
+
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
property->getGetterName(),
- property->getType(), nullptr, CD,
+ resultTy, nullptr, CD,
/*isInstance=*/true, /*isVariadic=*/false,
/*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
@@ -2015,12 +2099,25 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
+ // If the property is null_resettable, the setter accepts a
+ // nullable value.
+ QualType paramTy = property->getType().getUnqualifiedType();
+ if (property->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_null_resettable) {
+ QualType modifiedTy = paramTy;
+ if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
+ if (*nullability == NullabilityKind::Unspecified)
+ paramTy = Context.getAttributedType(AttributedType::attr_nullable,
+ modifiedTy, modifiedTy);
+ }
+ }
+
// Invent the arguments for the setter. We don't bother making a
// nice name for the argument.
ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
Loc, Loc,
property->getIdentifier(),
- property->getType().getUnqualifiedType(),
+ paramTy,
/*TInfo=*/nullptr,
SC_None,
nullptr);
@@ -2192,6 +2289,22 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
}
+ if (Attributes & ObjCDeclSpec::DQ_PR_weak) {
+ // 'weak' and 'nonnull' are mutually exclusive.
+ if (auto nullability = PropertyTy->getNullability(Context)) {
+ if (*nullability == NullabilityKind::NonNull)
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+ << "nonnull" << "weak";
+ } else {
+ PropertyTy =
+ Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable),
+ PropertyTy, PropertyTy);
+ TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo();
+ PropertyDecl->setType(PropertyTy, TSInfo);
+ }
+ }
+
if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) &&
(Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) {
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index d72942a..4030d9e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -82,10 +83,12 @@ private:
};
typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
+ typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy;
struct SharingMapTy {
DeclSAMapTy SharingMap;
AlignedMapTy AlignedMap;
+ LoopControlVariablesSetTy LCVSet;
DefaultDataSharingAttributes DefaultAttr;
SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
@@ -93,22 +96,29 @@ private:
Scope *CurScope;
SourceLocation ConstructLoc;
bool OrderedRegion;
+ bool NowaitRegion;
+ unsigned CollapseNumber;
SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
- : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
- ConstructLoc(Loc), OrderedRegion(false), InnerTeamsRegionLoc() {}
+ ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false),
+ CollapseNumber(1), InnerTeamsRegionLoc() {}
SharingMapTy()
- : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
- ConstructLoc(), OrderedRegion(false), InnerTeamsRegionLoc() {}
+ ConstructLoc(), OrderedRegion(false), NowaitRegion(false),
+ CollapseNumber(1), InnerTeamsRegionLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
/// \brief Stack of used declaration and their data-sharing attributes.
StackTy Stack;
+ /// \brief true, if check for DSA must be from parent directive, false, if
+ /// from current directive.
+ OpenMPClauseKind ClauseKindMode;
Sema &SemaRef;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
@@ -119,7 +129,11 @@ private:
bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
public:
- explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
+ explicit DSAStackTy(Sema &S)
+ : Stack(1), ClauseKindMode(OMPC_unknown), SemaRef(S) {}
+
+ bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
+ void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
Scope *CurScope, SourceLocation Loc) {
@@ -137,6 +151,12 @@ public:
/// for diagnostics.
DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE);
+ /// \brief Register specified variable as loop control variable.
+ void addLoopControlVariable(VarDecl *D);
+ /// \brief Check if the specified variable is a loop control variable for
+ /// current region.
+ bool isLoopControlVariable(VarDecl *D);
+
/// \brief Adds explicit data sharing attribute to the specified declaration.
void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
@@ -158,6 +178,12 @@ public:
DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred,
bool FromParent);
+ /// \brief Checks if the specified variables has explicit data-sharing
+ /// attributes which match specified \a CPred predicate at the specified
+ /// OpenMP region.
+ bool hasExplicitDSA(VarDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
+ unsigned Level);
/// \brief Finds a directive which matches specified \a DPred predicate.
template <class NamedDirectivesPredicate>
bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent);
@@ -208,6 +234,24 @@ public:
return Stack[Stack.size() - 2].OrderedRegion;
return false;
}
+ /// \brief Marks current region as nowait (it has a 'nowait' clause).
+ void setNowaitRegion(bool IsNowait = true) {
+ Stack.back().NowaitRegion = IsNowait;
+ }
+ /// \brief Returns true, if parent region is nowait (has associated
+ /// 'nowait' clause), false - otherwise.
+ bool isParentNowaitRegion() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].NowaitRegion;
+ return false;
+ }
+
+ /// \brief Set collapse value for the region.
+ void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; }
+ /// \brief Return collapse value for region.
+ unsigned getCollapseNumber() const {
+ return Stack.back().CollapseNumber;
+ }
/// \brief Marks current target region as one with closely nested teams
/// region.
@@ -238,6 +282,7 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
VarDecl *D) {
+ D = D->getCanonicalDecl();
DSAVarData DVar;
if (Iter == std::prev(Stack.rend())) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -308,8 +353,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// bound to the current team is shared.
if (DVar.DKind == OMPD_task) {
DSAVarData DVarTemp;
- for (StackTy::reverse_iterator I = std::next(Iter),
- EE = std::prev(Stack.rend());
+ for (StackTy::reverse_iterator I = std::next(Iter), EE = Stack.rend();
I != EE; ++I) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
// Referenced
@@ -343,6 +387,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
auto It = Stack.back().AlignedMap.find(D);
if (It == Stack.back().AlignedMap.end()) {
assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
@@ -355,7 +400,20 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
return nullptr;
}
+void DSAStackTy::addLoopControlVariable(VarDecl *D) {
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
+ Stack.back().LCVSet.insert(D);
+}
+
+bool DSAStackTy::isLoopControlVariable(VarDecl *D) {
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
+ return Stack.back().LCVSet.count(D) > 0;
+}
+
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
+ D = D->getCanonicalDecl();
if (A == OMPC_threadprivate) {
Stack[0].SharingMap[D].Attributes = A;
Stack[0].SharingMap[D].RefExpr = E;
@@ -367,6 +425,7 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
}
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+ D = D->getCanonicalDecl();
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = std::prev(Stack.rend());
Scope *TopScope = nullptr;
@@ -385,16 +444,44 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
return false;
}
+/// \brief Build a variable declaration for OpenMP loop iteration variable.
+static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
+ StringRef Name) {
+ DeclContext *DC = SemaRef.CurContext;
+ IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
+ TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
+ VarDecl *Decl =
+ VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
+ Decl->setImplicit();
+ return Decl;
+}
+
+static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
+ SourceLocation Loc,
+ bool RefersToCapture = false) {
+ D->setReferenced();
+ D->markUsed(S.Context);
+ return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
+ SourceLocation(), D, RefersToCapture, Loc, Ty,
+ VK_LValue);
+}
+
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
+ D = D->getCanonicalDecl();
DSAVarData DVar;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables appearing in threadprivate directives are threadprivate.
- if (D->getTLSKind() != VarDecl::TLS_None ||
- D->getStorageClass() == SC_Register) {
- DVar.CKind = OMPC_threadprivate;
- return DVar;
+ if ((D->getTLSKind() != VarDecl::TLS_None &&
+ !(D->hasAttr<OMPThreadPrivateDeclAttr>() &&
+ SemaRef.getLangOpts().OpenMPUseTLS &&
+ SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
+ (D->getStorageClass() == SC_Register && D->hasAttr<AsmLabelAttr>() &&
+ !D->isLocalVarDecl())) {
+ addDSA(D, buildDeclRefExpr(SemaRef, D, D->getType().getNonReferenceType(),
+ D->getLocation()),
+ OMPC_threadprivate);
}
if (Stack[0].SharingMap.count(D)) {
DVar.RefExpr = Stack[0].SharingMap[D].RefExpr;
@@ -421,29 +508,28 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
DVar.CKind = OMPC_private;
return DVar;
}
- }
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.4]
- // Static data members are shared.
- if (D->isStaticDataMember()) {
- // Variables with const-qualified type having no mutable member may be
- // listed in a firstprivate clause, even if they are static data members.
- DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
- MatchesAlways(), FromParent);
- if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
- return DVar;
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.4]
+ // Static data members are shared.
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.7]
+ // Variables with static storage duration that are declared in a scope
+ // inside the construct are shared.
+ if (D->isStaticDataMember() || D->isStaticLocal()) {
+ DSAVarData DVarTemp =
+ hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
+ if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
+ return DVar;
- DVar.CKind = OMPC_shared;
- return DVar;
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
}
QualType Type = D->getType().getNonReferenceType().getCanonicalType();
bool IsConstant = Type.isConstant(SemaRef.getASTContext());
- while (Type->isArrayType()) {
- QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
- Type = ElemType.getNonReferenceType().getCanonicalType();
- }
+ Type = SemaRef.getASTContext().getBaseElementType(Type);
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.6]
// Variables with const qualified type having no mutable member are
@@ -463,15 +549,6 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
return DVar;
}
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.7]
- // Variables with static storage duration that are declared in a scope
- // inside the construct are shared.
- if (D->isStaticLocal()) {
- DVar.CKind = OMPC_shared;
- return DVar;
- }
-
// Explicitly specified attributes and local variables with predetermined
// attributes.
auto I = std::prev(StartI);
@@ -485,6 +562,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
}
DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = Stack.rbegin();
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -497,6 +575,7 @@ template <class ClausesPredicate, class DirectivesPredicate>
DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred,
bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = std::next(Stack.rbegin());
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -516,6 +595,7 @@ template <class ClausesPredicate, class DirectivesPredicate>
DSAStackTy::DSAVarData
DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred, bool FromParent) {
+ D = D->getCanonicalDecl();
auto StartI = std::next(Stack.rbegin());
auto EndI = std::prev(Stack.rend());
if (FromParent && StartI != EndI) {
@@ -532,6 +612,23 @@ DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
return DSAVarData();
}
+bool DSAStackTy::hasExplicitDSA(
+ VarDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
+ unsigned Level) {
+ if (CPred(ClauseKindMode))
+ return true;
+ if (isClauseParsingMode())
+ ++Level;
+ D = D->getCanonicalDecl();
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (std::distance(StartI, EndI) <= (int)Level)
+ return false;
+ std::advance(StartI, Level);
+ return (StartI->SharingMap.count(D) > 0) && StartI->SharingMap[D].RefExpr &&
+ CPred(StartI->SharingMap[D].Attributes);
+}
+
template <class NamedDirectivesPredicate>
bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
auto StartI = std::next(Stack.rbegin());
@@ -554,17 +651,28 @@ void Sema::InitDataSharingAttributesStack() {
bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ VD = VD->getCanonicalDecl();
if (DSAStack->getCurrentDirective() != OMPD_unknown) {
- auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false);
+ if (DSAStack->isLoopControlVariable(VD) ||
+ (VD->hasLocalStorage() &&
+ isParallelOrTaskRegion(DSAStack->getCurrentDirective())))
+ return true;
+ auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
return true;
DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(),
- /*FromParent=*/false);
+ DSAStack->isClauseParsingMode());
return DVarPrivate.CKind != OMPC_unknown;
}
return false;
}
+bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ return DSAStack->hasExplicitDSA(
+ VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
+}
+
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
@@ -574,6 +682,14 @@ void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
PushExpressionEvaluationContext(PotentiallyEvaluated);
}
+void Sema::StartOpenMPClause(OpenMPClauseKind K) {
+ DSAStack->setClauseParsingMode(K);
+}
+
+void Sema::EndOpenMPClause() {
+ DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
+}
+
void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
// A variable of class type (or array thereof) that appears in a lastprivate
@@ -581,46 +697,41 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// class type, unless the list item is also specified in a firstprivate
// clause.
if (auto D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
- for (auto C : D->clauses()) {
- if (auto Clause = dyn_cast<OMPLastprivateClause>(C)) {
- for (auto VarRef : Clause->varlists()) {
- if (VarRef->isValueDependent() || VarRef->isTypeDependent())
+ for (auto *C : D->clauses()) {
+ if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
+ SmallVector<Expr *, 8> PrivateCopies;
+ for (auto *DE : Clause->varlists()) {
+ if (DE->isValueDependent() || DE->isTypeDependent()) {
+ PrivateCopies.push_back(nullptr);
continue;
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl());
+ }
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl());
+ QualType Type = VD->getType();
auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_lastprivate) {
- SourceLocation ELoc = VarRef->getExprLoc();
- auto Type = VarRef->getType();
- if (Type->isArrayType())
- Type = QualType(Type->getArrayElementTypeNoTypeQual(), 0);
- CXXRecordDecl *RD =
- getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- // FIXME This code must be replaced by actual constructing of the
- // lastprivate variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(
- ELoc, CD, InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 0;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl
- : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
- }
+ // Generate helper private variable and initialize it with the
+ // default value. The address of the original variable is replaced
+ // by the address of the new private variable in CodeGen. This new
+ // variable is not added to IdResolver, so the code in the OpenMP
+ // region uses original variable for proper diagnostics.
+ auto *VDPrivate =
+ buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(),
+ VD->getName());
+ ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
+ if (VDPrivate->isInvalidDecl())
+ continue;
+ PrivateCopies.push_back(buildDeclRefExpr(
+ *this, VDPrivate, DE->getType(), DE->getExprLoc()));
+ } else {
+ // The variable is also a firstprivate, so initialization sequence
+ // for private copy is generated already.
+ PrivateCopies.push_back(nullptr);
}
}
+ // Set initializers to private copies if no errors were found.
+ if (PrivateCopies.size() == Clause->varlist_size()) {
+ Clause->setPrivateCopies(PrivateCopies);
+ }
}
}
}
@@ -630,6 +741,10 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
PopExpressionEvaluationContext();
}
+static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
+ Expr *NumIterations, Sema &SemaRef,
+ Scope *S);
+
namespace {
class VarDeclFilterCCC : public CorrectionCandidateCallback {
@@ -763,14 +878,14 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
// A threadprivate directive must lexically precede all references to any
// of the variables in its list.
- if (VD->isUsed()) {
+ if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) {
Diag(Id.getLoc(), diag::err_omp_var_used)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
return ExprError();
}
QualType ExprType = VD->getType().getNonReferenceType();
- ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_LValue, Id.getLoc());
+ ExprResult DE = buildDeclRefExpr(*this, VD, ExprType, Id.getLoc());
return DE;
}
@@ -821,6 +936,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
VarDecl *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
+ QualType QType = VD->getType();
+ if (QType->isDependentType() || QType->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
// OpenMP [2.9.2, Restrictions, C/C++, p.10]
// A threadprivate variable must not have an incomplete type.
if (RequireCompleteType(ILoc, VD->getType(),
@@ -841,9 +963,14 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
continue;
}
- // Check if this is a TLS variable.
- if (VD->getTLSKind() != VarDecl::TLS_None ||
- VD->getStorageClass() == SC_Register) {
+ // Check if this is a TLS variable. If TLS is not being supported, produce
+ // the corresponding diagnostic.
+ if ((VD->getTLSKind() != VarDecl::TLS_None &&
+ !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
+ getLangOpts().OpenMPUseTLS &&
+ getASTContext().getTargetInfo().isTLSSupported())) ||
+ (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
+ !VD->isLocalVarDecl())) {
Diag(ILoc, diag::err_omp_var_thread_local)
<< VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
bool IsDecl =
@@ -1121,7 +1248,11 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_parallel_sections: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
@@ -1129,11 +1260,28 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_task: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32Ty),
+ std::make_pair(".part_id.", KmpInt32Ty),
+ std::make_pair(".privates.",
+ Context.VoidPtrTy.withConst().withRestrict()),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
Params);
+ // Mark this captured region as inlined, because we don't use outlined
+ // function directly.
+ getCurCapturedRegion()->TheCapturedDecl->addAttr(
+ AlwaysInlineAttr::CreateImplicit(
+ Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
break;
}
case OMPD_ordered: {
@@ -1172,10 +1320,20 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_taskgroup: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
case OMPD_flush:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -1183,9 +1341,40 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
}
+StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
+ ArrayRef<OMPClause *> Clauses) {
+ if (!S.isUsable()) {
+ ActOnCapturedRegionError();
+ return StmtError();
+ }
+ // This is required for proper codegen.
+ for (auto *Clause : Clauses) {
+ if (isOpenMPPrivate(Clause->getClauseKind()) ||
+ Clause->getClauseKind() == OMPC_copyprivate) {
+ // Mark all variables in private list clauses as used in inner region.
+ for (auto *VarRef : Clause->children()) {
+ if (auto *E = cast_or_null<Expr>(VarRef)) {
+ MarkDeclarationsReferencedInExpr(E);
+ }
+ }
+ } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) &&
+ Clause->getClauseKind() == OMPC_schedule) {
+ // Mark all variables in private list clauses as used in inner region.
+ // Required for proper codegen of combined directives.
+ // TODO: add processing for other clauses.
+ if (auto *E = cast_or_null<Expr>(
+ cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) {
+ MarkDeclarationsReferencedInExpr(E);
+ }
+ }
+ }
+ return ActOnCapturedRegionEnd(S.get());
+}
+
static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
OpenMPDirectiveKind CurrentRegion,
const DeclarationNameInfo &CurrentName,
+ OpenMPDirectiveKind CancelRegion,
SourceLocation StartLoc) {
// Allowed nesting of constructs
// +------------------+-----------------+------------------------------------+
@@ -1207,11 +1396,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | taskyield | * |
// | parallel | barrier | * |
// | parallel | taskwait | * |
+ // | parallel | taskgroup | * |
// | parallel | flush | * |
// | parallel | ordered | + |
// | parallel | atomic | * |
// | parallel | target | * |
// | parallel | teams | + |
+ // | parallel | cancellation | |
+ // | | point | ! |
+ // | parallel | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1229,11 +1422,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | taskyield | * |
// | for | barrier | + |
// | for | taskwait | * |
+ // | for | taskgroup | * |
// | for | flush | * |
// | for | ordered | * (if construct is ordered) |
// | for | atomic | * |
// | for | target | * |
// | for | teams | + |
+ // | for | cancellation | |
+ // | | point | ! |
+ // | for | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
@@ -1251,11 +1448,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | taskyield | * |
// | master | barrier | + |
// | master | taskwait | * |
+ // | master | taskgroup | * |
// | master | flush | * |
// | master | ordered | + |
// | master | atomic | * |
// | master | target | * |
// | master | teams | + |
+ // | master | cancellation | |
+ // | | point | |
+ // | master | cancel | |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
@@ -1273,10 +1474,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | critical | taskyield | * |
// | critical | barrier | + |
// | critical | taskwait | * |
+ // | critical | taskgroup | * |
// | critical | ordered | + |
// | critical | atomic | * |
// | critical | target | * |
// | critical | teams | + |
+ // | critical | cancellation | |
+ // | | point | |
+ // | critical | cancel | |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1294,11 +1499,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | taskyield | |
// | simd | barrier | |
// | simd | taskwait | |
+ // | simd | taskgroup | |
// | simd | flush | |
// | simd | ordered | |
// | simd | atomic | |
// | simd | target | |
// | simd | teams | |
+ // | simd | cancellation | |
+ // | | point | |
+ // | simd | cancel | |
// +------------------+-----------------+------------------------------------+
// | for simd | parallel | |
// | for simd | for | |
@@ -1316,11 +1525,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for simd | taskyield | |
// | for simd | barrier | |
// | for simd | taskwait | |
+ // | for simd | taskgroup | |
// | for simd | flush | |
// | for simd | ordered | |
// | for simd | atomic | |
// | for simd | target | |
// | for simd | teams | |
+ // | for simd | cancellation | |
+ // | | point | |
+ // | for simd | cancel | |
// +------------------+-----------------+------------------------------------+
// | parallel for simd| parallel | |
// | parallel for simd| for | |
@@ -1338,11 +1551,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for simd| taskyield | |
// | parallel for simd| barrier | |
// | parallel for simd| taskwait | |
+ // | parallel for simd| taskgroup | |
// | parallel for simd| flush | |
// | parallel for simd| ordered | |
// | parallel for simd| atomic | |
// | parallel for simd| target | |
// | parallel for simd| teams | |
+ // | parallel for simd| cancellation | |
+ // | | point | |
+ // | parallel for simd| cancel | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1360,11 +1577,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | taskyield | * |
// | sections | barrier | + |
// | sections | taskwait | * |
+ // | sections | taskgroup | * |
// | sections | flush | * |
// | sections | ordered | + |
// | sections | atomic | * |
// | sections | target | * |
// | sections | teams | + |
+ // | sections | cancellation | |
+ // | | point | ! |
+ // | sections | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1382,11 +1603,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | taskyield | * |
// | section | barrier | + |
// | section | taskwait | * |
+ // | section | taskgroup | * |
// | section | flush | * |
// | section | ordered | + |
// | section | atomic | * |
// | section | target | * |
// | section | teams | + |
+ // | section | cancellation | |
+ // | | point | ! |
+ // | section | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1404,11 +1629,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | taskyield | * |
// | single | barrier | + |
// | single | taskwait | * |
+ // | single | taskgroup | * |
// | single | flush | * |
// | single | ordered | + |
// | single | atomic | * |
// | single | target | * |
// | single | teams | + |
+ // | single | cancellation | |
+ // | | point | |
+ // | single | cancel | |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1426,11 +1655,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | taskyield | * |
// | parallel for | barrier | + |
// | parallel for | taskwait | * |
+ // | parallel for | taskgroup | * |
// | parallel for | flush | * |
// | parallel for | ordered | * (if construct is ordered) |
// | parallel for | atomic | * |
// | parallel for | target | * |
// | parallel for | teams | + |
+ // | parallel for | cancellation | |
+ // | | point | ! |
+ // | parallel for | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1448,11 +1681,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| taskyield | * |
// | parallel sections| barrier | + |
// | parallel sections| taskwait | * |
+ // | parallel sections| taskgroup | * |
// | parallel sections| flush | * |
// | parallel sections| ordered | + |
// | parallel sections| atomic | * |
// | parallel sections| target | * |
// | parallel sections| teams | + |
+ // | parallel sections| cancellation | |
+ // | | point | ! |
+ // | parallel sections| cancel | ! |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
@@ -1470,11 +1707,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | taskyield | * |
// | task | barrier | + |
// | task | taskwait | * |
+ // | task | taskgroup | * |
// | task | flush | * |
// | task | ordered | + |
// | task | atomic | * |
// | task | target | * |
// | task | teams | + |
+ // | task | cancellation | |
+ // | | point | ! |
+ // | task | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | ordered | parallel | * |
// | ordered | for | + |
@@ -1492,11 +1733,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | ordered | taskyield | * |
// | ordered | barrier | + |
// | ordered | taskwait | * |
+ // | ordered | taskgroup | * |
// | ordered | flush | * |
// | ordered | ordered | + |
// | ordered | atomic | * |
// | ordered | target | * |
// | ordered | teams | + |
+ // | ordered | cancellation | |
+ // | | point | |
+ // | ordered | cancel | |
// +------------------+-----------------+------------------------------------+
// | atomic | parallel | |
// | atomic | for | |
@@ -1514,11 +1759,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | atomic | taskyield | |
// | atomic | barrier | |
// | atomic | taskwait | |
+ // | atomic | taskgroup | |
// | atomic | flush | |
// | atomic | ordered | |
// | atomic | atomic | |
// | atomic | target | |
// | atomic | teams | |
+ // | atomic | cancellation | |
+ // | | point | |
+ // | atomic | cancel | |
// +------------------+-----------------+------------------------------------+
// | target | parallel | * |
// | target | for | * |
@@ -1536,11 +1785,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | target | taskyield | * |
// | target | barrier | * |
// | target | taskwait | * |
+ // | target | taskgroup | * |
// | target | flush | * |
// | target | ordered | * |
// | target | atomic | * |
// | target | target | * |
// | target | teams | * |
+ // | target | cancellation | |
+ // | | point | |
+ // | target | cancel | |
// +------------------+-----------------+------------------------------------+
// | teams | parallel | * |
// | teams | for | + |
@@ -1558,11 +1811,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | teams | taskyield | + |
// | teams | barrier | + |
// | teams | taskwait | + |
+ // | teams | taskgroup | + |
// | teams | flush | + |
// | teams | ordered | + |
// | teams | atomic | + |
// | teams | target | + |
// | teams | teams | + |
+ // | teams | cancellation | |
+ // | | point | |
+ // | teams | cancel | |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1604,7 +1861,26 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// called from OpenMP regions with the required preconditions).
if (ParentRegion == OMPD_unknown)
return false;
- if (CurrentRegion == OMPD_master) {
+ if (CurrentRegion == OMPD_cancellation_point ||
+ CurrentRegion == OMPD_cancel) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A cancellation point construct for which construct-type-clause is
+ // taskgroup must be nested inside a task construct. A cancellation
+ // point construct for which construct-type-clause is not taskgroup must
+ // be closely nested inside an OpenMP construct that matches the type
+ // specified in construct-type-clause.
+ // A cancel construct for which construct-type-clause is taskgroup must be
+ // nested inside a task construct. A cancel construct for which
+ // construct-type-clause is not taskgroup must be closely nested inside an
+ // OpenMP construct that matches the type specified in
+ // construct-type-clause.
+ NestingProhibited =
+ !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) ||
+ (CancelRegion == OMPD_for && ParentRegion == OMPD_for) ||
+ (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||
+ (CancelRegion == OMPD_sections &&
+ (ParentRegion == OMPD_section || ParentRegion == OMPD_sections)));
+ } else if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
// atomic, or explicit task region.
@@ -1694,14 +1970,13 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
return false;
}
-StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
- const DeclarationNameInfo &DirName,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
+StmtResult Sema::ActOnOpenMPExecutableDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
StmtResult Res = StmtError();
- if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, StartLoc))
+ if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
+ StartLoc))
return StmtError();
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
@@ -1808,6 +2083,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
"No associated statement allowed for 'omp taskwait' directive");
Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);
break;
+ case OMPD_taskgroup:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp taskgroup' directive");
+ Res = ActOnOpenMPTaskgroupDirective(AStmt, StartLoc, EndLoc);
+ break;
case OMPD_flush:
assert(AStmt == nullptr &&
"No associated statement allowed for 'omp flush' directive");
@@ -1830,6 +2110,20 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
break;
+ case OMPD_cancellation_point:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp cancellation point' directive");
+ assert(AStmt == nullptr && "No associated statement allowed for 'omp "
+ "cancellation point' directive");
+ Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
+ break;
+ case OMPD_cancel:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp cancel' directive");
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp cancel' directive");
+ Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion);
+ break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -1914,7 +2208,7 @@ public:
TestIsStrictOp(false), SubtractStep(false) {}
/// \brief Check init-expr for canonical loop form and save loop counter
/// variable - #Var and its initialization value - #LB.
- bool CheckInit(Stmt *S);
+ bool CheckInit(Stmt *S, bool EmitDiags = true);
/// \brief Check test-expr for canonical form, save upper-bound (#UB), flags
/// for less/greater and for strict/non-strict comparison.
bool CheckCond(Expr *S);
@@ -1935,6 +2229,8 @@ public:
bool ShouldSubtractStep() const { return SubtractStep; }
/// \brief Build the expression to calculate the number of iterations.
Expr *BuildNumIterations(Scope *S, const bool LimitedType) const;
+ /// \brief Build the precondition expression for the loops.
+ Expr *BuildPreCond(Scope *S, Expr *Cond) const;
/// \brief Build reference expression to the counter be used for codegen.
Expr *BuildCounterVar() const;
/// \brief Build initization of the counter be used for codegen.
@@ -2052,7 +2348,7 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
return false;
}
-bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
+bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
// Check init-expr for canonical loop form and save loop counter
// variable - #Var and its initialization value - #LB.
// OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
@@ -2062,7 +2358,9 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
// pointer-type var = lb
//
if (!S) {
- SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
+ if (EmitDiags) {
+ SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
+ }
return true;
}
InitSrcRange = S->getSourceRange();
@@ -2078,7 +2376,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
if (Var->hasInit()) {
// Accept non-canonical init form here but emit ext. warning.
- if (Var->getInitStyle() != VarDecl::CInit)
+ if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
SemaRef.Diag(S->getLocStart(),
diag::ext_omp_loop_not_canonical_init)
<< S->getSourceRange();
@@ -2092,8 +2390,10 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE,
CE->getArg(1));
- SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
- << S->getSourceRange();
+ if (EmitDiags) {
+ SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
+ << S->getSourceRange();
+ }
return true;
}
@@ -2338,11 +2638,22 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
return Diff.get();
}
+Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
+ // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
+ bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics();
+ SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
+ auto CondExpr = SemaRef.BuildBinOp(
+ S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
+ : (TestIsStrictOp ? BO_GT : BO_GE),
+ LB, UB);
+ SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress);
+ // Otherwise use original loop conditon and evaluate it in runtime.
+ return CondExpr.isUsable() ? CondExpr.get() : Cond;
+}
+
/// \brief Build reference expression to the counter be used for codegen.
Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const {
- return DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
- GetIncrementSrcRange().getBegin(), Var, false,
- DefaultLoc, Var->getType(), VK_LValue);
+ return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc);
}
/// \brief Build initization of the counter be used for codegen.
@@ -2353,6 +2664,8 @@ Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; }
/// \brief Iteration space of a single for loop.
struct LoopIterationSpace {
+ /// \brief Condition of the loop.
+ Expr *PreCond;
/// \brief This expression calculates the number of iterations in the loop.
/// It is always possible to calculate it before starting the loop.
Expr *NumIterations;
@@ -2375,6 +2688,20 @@ struct LoopIterationSpace {
} // namespace
+void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
+ assert(getLangOpts().OpenMP && "OpenMP is not active.");
+ assert(Init && "Expected loop in canonical form.");
+ unsigned CollapseIteration = DSAStack->getCollapseNumber();
+ if (CollapseIteration > 0 &&
+ isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
+ OpenMPIterationSpaceChecker ISC(*this, ForLoc);
+ if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
+ DSAStack->addLoopControlVariable(ISC.GetLoopVar());
+ }
+ DSAStack->setCollapseNumber(CollapseIteration - 1);
+ }
+}
+
/// \brief Called on a for stmt to check and extract its iteration space
/// for further processing (such as collapsing).
static bool CheckOpenMPIterationSpace(
@@ -2453,32 +2780,27 @@ static bool CheckOpenMPIterationSpace(
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
- DVar.CKind != PredeterminedCKind) ||
+ DVar.CKind != OMPC_threadprivate && DVar.CKind != PredeterminedCKind) ||
(isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) &&
DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private &&
- DVar.CKind != OMPC_lastprivate)) &&
- (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
+ DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_threadprivate)) &&
+ ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) ||
+ DVar.RefExpr != nullptr)) {
SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
- ReportOriginalDSA(SemaRef, &DSA, Var, DVar, true);
+ if (DVar.RefExpr == nullptr)
+ DVar.CKind = PredeterminedCKind;
+ ReportOriginalDSA(SemaRef, &DSA, Var, DVar, /*IsLoopIterVar=*/true);
HasErrors = true;
} else if (LoopVarRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
// linear (for simd directives with the only one associated loop) or
// lastprivate (for simd directives with several collapsed loops).
- // FIXME: the next check and error message must be removed once the
- // capturing of global variables in loops is fixed.
if (DVar.CKind == OMPC_unknown)
DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),
/*FromParent=*/false);
- if (!Var->hasLocalStorage() && DVar.CKind == OMPC_unknown) {
- SemaRef.Diag(Init->getLocStart(), diag::err_omp_global_loop_var_dsa)
- << getOpenMPClauseName(PredeterminedCKind)
- << getOpenMPDirectiveName(DKind);
- HasErrors = true;
- } else
- DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind);
+ DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind);
}
assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
@@ -2493,6 +2815,7 @@ static bool CheckOpenMPIterationSpace(
return HasErrors;
// Build the loop's iteration space representation.
+ ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond());
ResultIterSpace.NumIterations = ISC.BuildNumIterations(
DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind));
ResultIterSpace.CounterVar = ISC.BuildCounterVar();
@@ -2503,7 +2826,8 @@ static bool CheckOpenMPIterationSpace(
ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange();
ResultIterSpace.Subtract = ISC.ShouldSubtractStep();
- HasErrors |= (ResultIterSpace.NumIterations == nullptr ||
+ HasErrors |= (ResultIterSpace.PreCond == nullptr ||
+ ResultIterSpace.NumIterations == nullptr ||
ResultIterSpace.CounterVar == nullptr ||
ResultIterSpace.CounterInit == nullptr ||
ResultIterSpace.CounterStep == nullptr);
@@ -2511,18 +2835,6 @@ static bool CheckOpenMPIterationSpace(
return HasErrors;
}
-/// \brief Build a variable declaration for OpenMP loop iteration variable.
-static VarDecl *BuildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name) {
- DeclContext *DC = SemaRef.CurContext;
- IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
- TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl =
- VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
- Decl->setImplicit();
- return Decl;
-}
-
/// \brief Build 'VarRef = Start + Iter * Step'.
static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S,
SourceLocation Loc, ExprResult VarRef,
@@ -2648,6 +2960,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
// the iteration counts of the collapsed for loops.
+ // Precondition tests if there is at least one iteration (all conditions are
+ // true).
+ auto PreCond = ExprResult(IterSpaces[0].PreCond);
auto N0 = IterSpaces[0].NumIterations;
ExprResult LastIteration32 = WidenIterationCount(32 /* Bits */, N0, SemaRef);
ExprResult LastIteration64 = WidenIterationCount(64 /* Bits */, N0, SemaRef);
@@ -2660,6 +2975,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
Scope *CurScope = DSA.getCurScope();
for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
+ if (PreCond.isUsable()) {
+ PreCond = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LAnd,
+ PreCond.get(), IterSpaces[Cnt].PreCond);
+ }
auto N = IterSpaces[Cnt].NumIterations;
AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
if (LastIteration32.isUsable())
@@ -2703,10 +3022,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
if (!IsConstant) {
SourceLocation SaveLoc;
VarDecl *SaveVar =
- BuildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(),
+ buildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(),
".omp.last.iteration");
- ExprResult SaveRef = SemaRef.BuildDeclRefExpr(
- SaveVar, LastIteration.get()->getType(), VK_LValue, SaveLoc);
+ ExprResult SaveRef = buildDeclRefExpr(
+ SemaRef, SaveVar, LastIteration.get()->getType(), SaveLoc);
CalcLastIteration = SemaRef.BuildBinOp(CurScope, SaveLoc, BO_Assign,
SaveRef.get(), LastIteration.get());
LastIteration = SaveRef;
@@ -2721,25 +3040,20 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
- // Precondition tests if there is at least one iteration (LastIteration > 0).
- ExprResult PreCond = SemaRef.BuildBinOp(
- CurScope, InitLoc, BO_GT, LastIteration.get(),
- SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get());
-
QualType VType = LastIteration.get()->getType();
// Build variables passed into runtime, nesessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB;
if (isOpenMPWorksharingDirective(DKind)) {
// Lower bound variable, initialized with zero.
- VarDecl *LBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
- LB = SemaRef.BuildDeclRefExpr(LBDecl, VType, VK_LValue, InitLoc);
+ VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
+ LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(
LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
// Upper bound variable, initialized with last iteration number.
- VarDecl *UBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
- UB = SemaRef.BuildDeclRefExpr(UBDecl, VType, VK_LValue, InitLoc);
+ VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
+ UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
/*DirectInit*/ false,
/*TypeMayContainAuto*/ false);
@@ -2747,15 +3061,15 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// A 32-bit variable-flag where runtime returns 1 for the last iteration.
// This will be used to implement clause 'lastprivate'.
QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
- VarDecl *ILDecl = BuildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
- IL = SemaRef.BuildDeclRefExpr(ILDecl, Int32Ty, VK_LValue, InitLoc);
+ VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
+ IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
SemaRef.AddInitializerToDecl(
ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
// Stride variable returned by runtime (we initialize it to 1 by default).
- VarDecl *STDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.stride");
- ST = SemaRef.BuildDeclRefExpr(STDecl, VType, VK_LValue, InitLoc);
+ VarDecl *STDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.stride");
+ ST = buildDeclRefExpr(SemaRef, STDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(
STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
@@ -2775,8 +3089,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
ExprResult IV;
ExprResult Init;
{
- VarDecl *IVDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");
- IV = SemaRef.BuildDeclRefExpr(IVDecl, VType, VK_LValue, InitLoc);
+ VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");
+ IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc);
Expr *RHS = isOpenMPWorksharingDirective(DKind)
? LB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
@@ -2791,9 +3105,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
: SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
NumIterations.get());
- // Loop condition with 1 iteration separated (IV < LastIteration)
- ExprResult SeparatedCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT,
- IV.get(), LastIteration.get());
// Loop increment (IV = IV + 1)
SourceLocation IncLoc;
@@ -2864,9 +3175,13 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
break;
}
- // Build update: IS.CounterVar = IS.Start + Iter * IS.Step
+ // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
+ auto *CounterVar = buildDeclRefExpr(
+ SemaRef, cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()),
+ IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
+ /*RefersToCapture=*/true);
ExprResult Update =
- BuildCounterUpdate(SemaRef, CurScope, UpdLoc, IS.CounterVar,
+ BuildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
IS.CounterInit, Iter, IS.CounterStep, IS.Subtract);
if (!Update.isUsable()) {
HasErrors = true;
@@ -2875,7 +3190,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
ExprResult Final = BuildCounterUpdate(
- SemaRef, CurScope, UpdLoc, IS.CounterVar, IS.CounterInit,
+ SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
IS.NumIterations, IS.CounterStep, IS.Subtract);
if (!Final.isUsable()) {
HasErrors = true;
@@ -2915,10 +3230,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Save results
Built.IterationVarRef = IV.get();
Built.LastIteration = LastIteration.get();
+ Built.NumIterations = NumIterations.get();
Built.CalcLastIteration = CalcLastIteration.get();
Built.PreCond = PreCond.get();
Built.Cond = Cond.get();
- Built.SeparatedCond = SeparatedCond.get();
Built.Init = Init.get();
Built.Inc = Inc.get();
Built.LB = LB.get();
@@ -2933,11 +3248,11 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
}
static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
- auto CollapseFilter = [](const OMPClause *C) -> bool {
+ auto &&CollapseFilter = [](const OMPClause *C) -> bool {
return C->getClauseKind() == OMPC_collapse;
};
OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I(
- Clauses, CollapseFilter);
+ Clauses, std::move(CollapseFilter));
if (I)
return cast<OMPCollapseClause>(*I)->getNumForLoops();
return nullptr;
@@ -2958,6 +3273,16 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp simd loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -2998,6 +3323,16 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for simd loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -3017,8 +3352,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (++S; S; ++S) {
- auto SectionStmt = *S;
+ for (Stmt *SectionStmt : ++S) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
@@ -3055,6 +3389,23 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
+ // OpenMP [2.7.3, single Construct, Restrictions]
+ // The copyprivate clause must not be used with the nowait clause.
+ OMPClause *Nowait = nullptr;
+ OMPClause *Copyprivate = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_nowait)
+ Nowait = Clause;
+ else if (Clause->getClauseKind() == OMPC_copyprivate)
+ Copyprivate = Clause;
+ if (Copyprivate && Nowait) {
+ Diag(Copyprivate->getLocStart(),
+ diag::err_omp_single_copyprivate_with_nowait);
+ Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here);
+ return StmtError();
+ }
+ }
+
return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -3130,6 +3481,16 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (NestedLoopCount == 0)
return StmtError();
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
@@ -3149,8 +3510,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (++S; S; ++S) {
- auto SectionStmt = *S;
+ for (Stmt *SectionStmt : ++S) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
@@ -3202,6 +3562,16 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc);
}
+StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, AStmt);
+}
+
StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc) {
@@ -3219,6 +3589,246 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt,
return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
+namespace {
+/// \brief Helper class for checking expression in 'omp atomic [update]'
+/// construct.
+class OpenMPAtomicUpdateChecker {
+ /// \brief Error results for atomic update expressions.
+ enum ExprAnalysisErrorCode {
+ /// \brief A statement is not an expression statement.
+ NotAnExpression,
+ /// \brief Expression is not builtin binary or unary operation.
+ NotABinaryOrUnaryExpression,
+ /// \brief Unary operation is not post-/pre- increment/decrement operation.
+ NotAnUnaryIncDecExpression,
+ /// \brief An expression is not of scalar type.
+ NotAScalarType,
+ /// \brief A binary operation is not an assignment operation.
+ NotAnAssignmentOp,
+ /// \brief RHS part of the binary operation is not a binary expression.
+ NotABinaryExpression,
+ /// \brief RHS part is not additive/multiplicative/shift/biwise binary
+ /// expression.
+ NotABinaryOperator,
+ /// \brief RHS binary operation does not have reference to the updated LHS
+ /// part.
+ NotAnUpdateExpression,
+ /// \brief No errors is found.
+ NoError
+ };
+ /// \brief Reference to Sema.
+ Sema &SemaRef;
+ /// \brief A location for note diagnostics (when error is found).
+ SourceLocation NoteLoc;
+ /// \brief 'x' lvalue part of the source atomic expression.
+ Expr *X;
+ /// \brief 'expr' rvalue part of the source atomic expression.
+ Expr *E;
+ /// \brief Helper expression of the form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ Expr *UpdateExpr;
+ /// \brief Is 'x' a LHS in a RHS part of full update expression. It is
+ /// important for non-associative operations.
+ bool IsXLHSInRHSPart;
+ BinaryOperatorKind Op;
+ SourceLocation OpLoc;
+ /// \brief true if the source expression is a postfix unary operation, false
+ /// if it is a prefix unary operation.
+ bool IsPostfixUpdate;
+
+public:
+ OpenMPAtomicUpdateChecker(Sema &SemaRef)
+ : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
+ IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
+ /// \brief Check specified statement that it is suitable for 'atomic update'
+ /// constructs and extract 'x', 'expr' and Operation from the original
+ /// expression. If DiagId and NoteId == 0, then only check is performed
+ /// without error notification.
+ /// \param DiagId Diagnostic which should be emitted if error is found.
+ /// \param NoteId Diagnostic note for the main error message.
+ /// \return true if statement is not an update expression, false otherwise.
+ bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
+ /// \brief Return the 'x' lvalue part of the source atomic expression.
+ Expr *getX() const { return X; }
+ /// \brief Return the 'expr' rvalue part of the source atomic expression.
+ Expr *getExpr() const { return E; }
+ /// \brief Return the update expression used in calculation of the updated
+ /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ Expr *getUpdateExpr() const { return UpdateExpr; }
+ /// \brief Return true if 'x' is LHS in RHS part of full update expression,
+ /// false otherwise.
+ bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
+
+ /// \brief true if the source expression is a postfix unary operation, false
+ /// if it is a prefix unary operation.
+ bool isPostfixUpdate() const { return IsPostfixUpdate; }
+
+private:
+ bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
+ unsigned NoteId = 0);
+};
+} // namespace
+
+bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
+ BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
+ ExprAnalysisErrorCode ErrorFound = NoError;
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ // Allowed constructs are:
+ // x = x binop expr;
+ // x = expr binop x;
+ if (AtomicBinOp->getOpcode() == BO_Assign) {
+ X = AtomicBinOp->getLHS();
+ if (auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
+ AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
+ if (AtomicInnerBinOp->isMultiplicativeOp() ||
+ AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
+ AtomicInnerBinOp->isBitwiseOp()) {
+ Op = AtomicInnerBinOp->getOpcode();
+ OpLoc = AtomicInnerBinOp->getOperatorLoc();
+ auto *LHS = AtomicInnerBinOp->getLHS();
+ auto *RHS = AtomicInnerBinOp->getRHS();
+ llvm::FoldingSetNodeID XId, LHSId, RHSId;
+ X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
+ /*Canonical=*/true);
+ LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
+ /*Canonical=*/true);
+ RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
+ /*Canonical=*/true);
+ if (XId == LHSId) {
+ E = RHS;
+ IsXLHSInRHSPart = true;
+ } else if (XId == RHSId) {
+ E = LHS;
+ IsXLHSInRHSPart = false;
+ } else {
+ ErrorLoc = AtomicInnerBinOp->getExprLoc();
+ ErrorRange = AtomicInnerBinOp->getSourceRange();
+ NoteLoc = X->getExprLoc();
+ NoteRange = X->getSourceRange();
+ ErrorFound = NotAnUpdateExpression;
+ }
+ } else {
+ ErrorLoc = AtomicInnerBinOp->getExprLoc();
+ ErrorRange = AtomicInnerBinOp->getSourceRange();
+ NoteLoc = AtomicInnerBinOp->getOperatorLoc();
+ NoteRange = SourceRange(NoteLoc, NoteLoc);
+ ErrorFound = NotABinaryOperator;
+ }
+ } else {
+ NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
+ NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
+ ErrorFound = NotABinaryExpression;
+ }
+ } else {
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = AtomicBinOp->getOperatorLoc();
+ NoteRange = SourceRange(NoteLoc, NoteLoc);
+ ErrorFound = NotAnAssignmentOp;
+ }
+ if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
+ SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
+ SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
+ return true;
+ } else if (SemaRef.CurContext->isDependentContext())
+ E = X = UpdateExpr = nullptr;
+ return ErrorFound != NoError;
+}
+
+bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
+ unsigned NoteId) {
+ ExprAnalysisErrorCode ErrorFound = NoError;
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ // Allowed constructs are:
+ // x++;
+ // x--;
+ // ++x;
+ // --x;
+ // x binop= expr;
+ // x = x binop expr;
+ // x = expr binop x;
+ if (auto *AtomicBody = dyn_cast<Expr>(S)) {
+ AtomicBody = AtomicBody->IgnoreParenImpCasts();
+ if (AtomicBody->getType()->isScalarType() ||
+ AtomicBody->isInstantiationDependent()) {
+ if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
+ AtomicBody->IgnoreParenImpCasts())) {
+ // Check for Compound Assignment Operation
+ Op = BinaryOperator::getOpForCompoundAssignment(
+ AtomicCompAssignOp->getOpcode());
+ OpLoc = AtomicCompAssignOp->getOperatorLoc();
+ E = AtomicCompAssignOp->getRHS();
+ X = AtomicCompAssignOp->getLHS();
+ IsXLHSInRHSPart = true;
+ } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
+ AtomicBody->IgnoreParenImpCasts())) {
+ // Check for Binary Operation
+ if(checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
+ return true;
+ } else if (auto *AtomicUnaryOp =
+ dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) {
+ // Check for Unary Operation
+ if (AtomicUnaryOp->isIncrementDecrementOp()) {
+ IsPostfixUpdate = AtomicUnaryOp->isPostfix();
+ Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
+ OpLoc = AtomicUnaryOp->getOperatorLoc();
+ X = AtomicUnaryOp->getSubExpr();
+ E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
+ IsXLHSInRHSPart = true;
+ } else {
+ ErrorFound = NotAnUnaryIncDecExpression;
+ ErrorLoc = AtomicUnaryOp->getExprLoc();
+ ErrorRange = AtomicUnaryOp->getSourceRange();
+ NoteLoc = AtomicUnaryOp->getOperatorLoc();
+ NoteRange = SourceRange(NoteLoc, NoteLoc);
+ }
+ } else {
+ ErrorFound = NotABinaryOrUnaryExpression;
+ NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
+ NoteRange = ErrorRange = AtomicBody->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAScalarType;
+ NoteLoc = ErrorLoc = AtomicBody->getLocStart();
+ NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
+ }
+ } else {
+ ErrorFound = NotAnExpression;
+ NoteLoc = ErrorLoc = S->getLocStart();
+ NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
+ }
+ if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
+ SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
+ SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
+ return true;
+ } else if (SemaRef.CurContext->isDependentContext())
+ E = X = UpdateExpr = nullptr;
+ if (ErrorFound == NoError && E && X) {
+ // Build an update expression of form 'OpaqueValueExpr(x) binop
+ // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
+ // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
+ auto *OVEX = new (SemaRef.getASTContext())
+ OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue);
+ auto *OVEExpr = new (SemaRef.getASTContext())
+ OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue);
+ auto Update =
+ SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
+ IsXLHSInRHSPart ? OVEExpr : OVEX);
+ if (Update.isInvalid())
+ return true;
+ Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
+ Sema::AA_Casting);
+ if (Update.isInvalid())
+ return true;
+ UpdateExpr = Update.get();
+ }
+ return ErrorFound != NoError;
+}
+
StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
@@ -3230,7 +3840,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
- // TODO further analysis of associated statements and clauses.
OpenMPClauseKind AtomicKind = OMPC_unknown;
SourceLocation AtomicKindLoc;
for (auto *C : Clauses) {
@@ -3250,9 +3859,15 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
auto Body = CS->getCapturedStmt();
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
+ Body = EWC->getSubExpr();
+
Expr *X = nullptr;
Expr *V = nullptr;
Expr *E = nullptr;
+ Expr *UE = nullptr;
+ bool IsXLHSInRHSPart = false;
+ bool IsPostfixUpdate = false;
// OpenMP [2.12.6, atomic Construct]
// In the next expressions:
// * x and v (as applicable) are both l-value expressions with scalar type.
@@ -3275,14 +3890,14 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// expr or subexpressions of expr.
// * For forms that allow multiple occurrences of x, the number of times
// that x is evaluated is unspecified.
- enum {
- NotAnExpression,
- NotAnAssignmentOp,
- NotAScalarType,
- NotAnLValue,
- NoError
- } ErrorFound = NoError;
if (AtomicKind == OMPC_read) {
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
// If clause is read:
@@ -3338,6 +3953,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
} else if (CurContext->isDependentContext())
V = X = nullptr;
} else if (AtomicKind == OMPC_write) {
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
// If clause is write:
@@ -3346,8 +3968,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
auto AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
- X = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
- E = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ X = AtomicBinOp->getLHS();
+ E = AtomicBinOp->getRHS();
if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
(E->isInstantiationDependent() || E->getType()->isScalarType())) {
if (!X->isLValue()) {
@@ -3392,28 +4014,240 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
} else if (CurContext->isDependentContext())
E = X = nullptr;
} else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
- if (!isa<Expr>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_update_not_expression_statement)
- << (AtomicKind == OMPC_update);
+ // If clause is update:
+ // x++;
+ // x--;
+ // ++x;
+ // --x;
+ // x binop= expr;
+ // x = x binop expr;
+ // x = expr binop x;
+ OpenMPAtomicUpdateChecker Checker(*this);
+ if (Checker.checkStatement(
+ Body, (AtomicKind == OMPC_update)
+ ? diag::err_omp_atomic_update_not_expression_statement
+ : diag::err_omp_atomic_not_expression_statement,
+ diag::note_omp_atomic_update))
return StmtError();
+ if (!CurContext->isDependentContext()) {
+ E = Checker.getExpr();
+ X = Checker.getX();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
}
} else if (AtomicKind == OMPC_capture) {
- if (isa<Expr>(Body) && !isa<BinaryOperator>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_capture_not_expression_statement);
- return StmtError();
- } else if (!isa<Expr>(Body) && !isa<CompoundStmt>(Body)) {
- Diag(Body->getLocStart(),
- diag::err_omp_atomic_capture_not_compound_statement);
- return StmtError();
+ enum {
+ NotAnAssignmentOp,
+ NotACompoundStatement,
+ NotTwoSubstatements,
+ NotASpecificExpression,
+ NoError
+ } ErrorFound = NoError;
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ // If clause is a capture:
+ // v = x++;
+ // v = x--;
+ // v = ++x;
+ // v = --x;
+ // v = x binop= expr;
+ // v = x = x binop expr;
+ // v = x = expr binop x;
+ auto *AtomicBinOp =
+ dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+ if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+ V = AtomicBinOp->getLHS();
+ Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ OpenMPAtomicUpdateChecker Checker(*this);
+ if (Checker.checkStatement(
+ Body, diag::err_omp_atomic_capture_not_expression_statement,
+ diag::note_omp_atomic_update))
+ return StmtError();
+ E = Checker.getExpr();
+ X = Checker.getX();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = Checker.isPostfixUpdate();
+ } else {
+ ErrorLoc = AtomicBody->getExprLoc();
+ ErrorRange = AtomicBody->getSourceRange();
+ NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+ : AtomicBody->getExprLoc();
+ NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+ : AtomicBody->getSourceRange();
+ ErrorFound = NotAnAssignmentOp;
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext()) {
+ UE = V = E = X = nullptr;
+ }
+ } else {
+ // If clause is a capture:
+ // { v = x; x = expr; }
+ // { v = x; x++; }
+ // { v = x; x--; }
+ // { v = x; ++x; }
+ // { v = x; --x; }
+ // { v = x; x binop= expr; }
+ // { v = x; x = x binop expr; }
+ // { v = x; x = expr binop x; }
+ // { x++; v = x; }
+ // { x--; v = x; }
+ // { ++x; v = x; }
+ // { --x; v = x; }
+ // { x binop= expr; v = x; }
+ // { x = x binop expr; v = x; }
+ // { x = expr binop x; v = x; }
+ if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+ // Check that this is { expr1; expr2; }
+ if (CS->size() == 2) {
+ auto *First = CS->body_front();
+ auto *Second = CS->body_back();
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
+ First = EWC->getSubExpr()->IgnoreParenImpCasts();
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
+ Second = EWC->getSubExpr()->IgnoreParenImpCasts();
+ // Need to find what subexpression is 'v' and what is 'x'.
+ OpenMPAtomicUpdateChecker Checker(*this);
+ bool IsUpdateExprFound = !Checker.checkStatement(Second);
+ BinaryOperator *BinOp = nullptr;
+ if (IsUpdateExprFound) {
+ BinOp = dyn_cast<BinaryOperator>(First);
+ IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
+ }
+ if (IsUpdateExprFound && !CurContext->isDependentContext()) {
+ // { v = x; x++; }
+ // { v = x; x--; }
+ // { v = x; ++x; }
+ // { v = x; --x; }
+ // { v = x; x binop= expr; }
+ // { v = x; x = x binop expr; }
+ // { v = x; x = expr binop x; }
+ // Check that the first expression has form v = x.
+ auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID XId, PossibleXId;
+ Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
+ PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
+ IsUpdateExprFound = XId == PossibleXId;
+ if (IsUpdateExprFound) {
+ V = BinOp->getLHS();
+ X = Checker.getX();
+ E = Checker.getExpr();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = true;
+ }
+ }
+ if (!IsUpdateExprFound) {
+ IsUpdateExprFound = !Checker.checkStatement(First);
+ BinOp = nullptr;
+ if (IsUpdateExprFound) {
+ BinOp = dyn_cast<BinaryOperator>(Second);
+ IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
+ }
+ if (IsUpdateExprFound && !CurContext->isDependentContext()) {
+ // { x++; v = x; }
+ // { x--; v = x; }
+ // { ++x; v = x; }
+ // { --x; v = x; }
+ // { x binop= expr; v = x; }
+ // { x = x binop expr; v = x; }
+ // { x = expr binop x; v = x; }
+ // Check that the second expression has form v = x.
+ auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID XId, PossibleXId;
+ Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
+ PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
+ IsUpdateExprFound = XId == PossibleXId;
+ if (IsUpdateExprFound) {
+ V = BinOp->getLHS();
+ X = Checker.getX();
+ E = Checker.getExpr();
+ UE = Checker.getUpdateExpr();
+ IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
+ IsPostfixUpdate = false;
+ }
+ }
+ }
+ if (!IsUpdateExprFound) {
+ // { v = x; x = expr; }
+ auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
+ if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
+ : First->getLocStart();
+ NoteRange = ErrorRange = FirstBinOp
+ ? FirstBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
+ } else {
+ auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
+ if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc()
+ : Second->getLocStart();
+ NoteRange = ErrorRange = SecondBinOp
+ ? SecondBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
+ } else {
+ auto *PossibleXRHSInFirst =
+ FirstBinOp->getRHS()->IgnoreParenImpCasts();
+ auto *PossibleXLHSInSecond =
+ SecondBinOp->getLHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID X1Id, X2Id;
+ PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true);
+ PossibleXLHSInSecond->Profile(X2Id, Context,
+ /*Canonical=*/true);
+ IsUpdateExprFound = X1Id == X2Id;
+ if (IsUpdateExprFound) {
+ V = FirstBinOp->getLHS();
+ X = SecondBinOp->getLHS();
+ E = SecondBinOp->getRHS();
+ UE = nullptr;
+ IsXLHSInRHSPart = false;
+ IsPostfixUpdate = true;
+ } else {
+ ErrorFound = NotASpecificExpression;
+ ErrorLoc = FirstBinOp->getExprLoc();
+ ErrorRange = FirstBinOp->getSourceRange();
+ NoteLoc = SecondBinOp->getLHS()->getExprLoc();
+ NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ }
+ }
+ }
+ }
+ } else {
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange =
+ SourceRange(Body->getLocStart(), Body->getLocStart());
+ ErrorFound = NotTwoSubstatements;
+ }
+ } else {
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange =
+ SourceRange(Body->getLocStart(), Body->getLocStart());
+ ErrorFound = NotACompoundStatement;
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext()) {
+ UE = V = E = X = nullptr;
+ }
}
}
getCurFunction()->setHasBranchProtectedScope();
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
- X, V, E);
+ X, V, E, UE, IsXLHSInRHSPart,
+ IsPostfixUpdate);
}
StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
@@ -3474,6 +4308,48 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
+StmtResult
+Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
+ CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) {
+ Diag(StartLoc, diag::err_omp_wrong_cancel_region)
+ << getOpenMPDirectiveName(CancelRegion);
+ return StmtError();
+ }
+ if (DSAStack->isParentNowaitRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
+ return StmtError();
+ }
+ if (DSAStack->isParentOrderedRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
+ return StmtError();
+ }
+ return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
+ CancelRegion);
+}
+
+StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
+ CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) {
+ Diag(StartLoc, diag::err_omp_wrong_cancel_region)
+ << getOpenMPDirectiveName(CancelRegion);
+ return StmtError();
+ }
+ if (DSAStack->isParentNowaitRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
+ return StmtError();
+ }
+ if (DSAStack->isParentOrderedRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
+ return StmtError();
+ }
+ return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -3518,6 +4394,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -3655,6 +4532,9 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
<< E->getSourceRange();
return ExprError();
}
+ if (CKind == OMPC_collapse) {
+ DSAStack->setCollapseNumber(Result.getExtValue());
+ }
return ICE;
}
@@ -3729,6 +4609,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -3849,6 +4730,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -3882,6 +4764,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
return nullptr;
}
Expr *ValExpr = ChunkSize;
+ Expr *HelperValExpr = nullptr;
if (ChunkSize) {
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
@@ -3898,17 +4781,25 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
// chunk_size must be a loop invariant integer expression with a positive
// value.
llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context) &&
- Result.isSigned() && !Result.isStrictlyPositive()) {
- Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
- << "schedule" << ChunkSize->getSourceRange();
- return nullptr;
+ if (ValExpr->isIntegerConstantExpr(Result, Context)) {
+ if (Result.isSigned() && !Result.isStrictlyPositive()) {
+ Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
+ << "schedule" << ChunkSize->getSourceRange();
+ return nullptr;
+ }
+ } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
+ auto *ImpVar = buildVarDecl(*this, ChunkSize->getExprLoc(),
+ ChunkSize->getType(), ".chunk.");
+ auto *ImpVarRef = buildDeclRefExpr(*this, ImpVar, ChunkSize->getType(),
+ ChunkSize->getExprLoc(),
+ /*RefersToCapture=*/true);
+ HelperValExpr = ImpVarRef;
}
}
}
return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
- EndLoc, Kind, ValExpr);
+ EndLoc, Kind, ValExpr, HelperValExpr);
}
OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
@@ -3962,6 +4853,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -3976,6 +4868,7 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
+ DSAStack->setNowaitRegion();
return new (Context) OMPNowaitClause(StartLoc, EndLoc);
}
@@ -4018,7 +4911,8 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId) {
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
@@ -4054,6 +4948,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_flush:
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_depend:
+ Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc,
+ LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -4133,14 +5031,6 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
continue;
}
- // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
- // A variable of class type (or array thereof) that appears in a private
- // clause requires an accessible, unambiguous default constructor for the
- // class type.
- while (Type->isArrayType()) {
- Type = cast<ArrayType>(Type.getTypePtr())->getElementType();
- }
-
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
// Variables with the predetermined data-sharing attributes may not be
@@ -4156,25 +5046,36 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
continue;
}
+ // Variably modified types are not supported for tasks.
+ if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
+ DSAStack->getCurrentDirective() == OMPD_task) {
+ Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
+ << getOpenMPClauseName(OMPC_private) << Type
+ << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
+ // A variable of class type (or array thereof) that appears in a private
+ // clause requires an accessible, unambiguous default constructor for the
+ // class type.
// Generate helper private variable and initialize it with the default
// value. The address of the original variable is replaced by the address of
// the new private variable in CodeGen. This new variable is not added to
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
- auto VDPrivate =
- VarDecl::Create(Context, CurContext, DE->getLocStart(),
- DE->getExprLoc(), VD->getIdentifier(), VD->getType(),
- VD->getTypeSourceInfo(), /*S*/ SC_Auto);
- ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto*/ false);
+ Type = Type.getUnqualifiedType();
+ auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName());
+ ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
if (VDPrivate->isInvalidDecl())
continue;
- CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr =
- DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
- /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
- /*RefersToEnclosingVariableOrCapture*/ false,
- /*NameLoc*/ SourceLocation(), DE->getType(),
- /*VK*/ VK_LValue);
+ auto VDPrivateRefExpr = buildDeclRefExpr(
+ *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc());
DSAStack->addDSA(VD, DE, OMPC_private);
Vars.push_back(DE);
@@ -4285,14 +5186,12 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a private
// clause requires an accessible, unambiguous copy constructor for the
// class type.
- Type = Context.getBaseElementType(Type);
+ auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
// If an implicit firstprivate variable found it was checked already.
if (!IsImplicitClause) {
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
- Type = Type.getNonReferenceType().getCanonicalType();
- bool IsConstant = Type.isConstant(Context);
- Type = Context.getBaseElementType(Type);
+ bool IsConstant = ElemType.isConstant(Context);
// OpenMP [2.4.13, Data-sharing Attribute Clauses]
// A list item that specifies a given variable may not appear in more
// than one clause on the same directive, except that a variable may be
@@ -4375,10 +5274,22 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
}
+ // Variably modified types are not supported for tasks.
+ if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
+ DSAStack->getCurrentDirective() == OMPD_task) {
+ Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
+ << getOpenMPClauseName(OMPC_firstprivate) << Type
+ << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
Type = Type.getUnqualifiedType();
- auto VDPrivate = VarDecl::Create(Context, CurContext, DE->getLocStart(),
- ELoc, VD->getIdentifier(), VD->getType(),
- VD->getTypeSourceInfo(), /*S*/ SC_Auto);
+ auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName());
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -4387,19 +5298,16 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Expr *VDInitRefExpr = nullptr;
// For arrays generate initializer for single element and replace it by the
// original array element in CodeGen.
- if (DE->getType()->isArrayType()) {
- auto VDInit = VarDecl::Create(Context, CurContext, DE->getLocStart(),
- ELoc, VD->getIdentifier(), Type,
- VD->getTypeSourceInfo(), /*S*/ SC_Auto);
- CurContext->addHiddenDecl(VDInit);
- VDInitRefExpr = DeclRefExpr::Create(
- Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
- /*TemplateKWLoc*/ SourceLocation(), VDInit,
- /*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type,
- /*VK*/ VK_LValue);
- VDInit->setIsUsed();
+ if (Type->isArrayType()) {
+ auto VDInit =
+ buildVarDecl(*this, DE->getExprLoc(), ElemType, VD->getName());
+ VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
- InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInit);
+ ElemType = ElemType.getUnqualifiedType();
+ auto *VDInitTemp = buildVarDecl(*this, DE->getLocStart(), ElemType,
+ ".firstprivate.temp");
+ InitializedEntity Entity =
+ InitializedEntity::InitializeVariable(VDInitTemp);
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
InitializationSequence InitSeq(*this, Entity, Kind, Init);
@@ -4409,15 +5317,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
else
VDPrivate->setInit(Result.getAs<Expr>());
} else {
- AddInitializerToDecl(
- VDPrivate,
- DefaultLvalueConversion(
- DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
- SourceLocation(), DE->getDecl(),
- /*RefersToEnclosingVariableOrCapture=*/true,
- DE->getExprLoc(), DE->getType(),
- /*VK=*/VK_LValue)).get(),
- /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ auto *VDInit =
+ buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp");
+ VDInitRefExpr =
+ buildDeclRefExpr(*this, VDInit, DE->getType(), DE->getExprLoc());
+ AddInitializerToDecl(VDPrivate,
+ DefaultLvalueConversion(VDInitRefExpr).get(),
+ /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
}
if (VDPrivate->isInvalidDecl()) {
if (IsImplicitClause) {
@@ -4427,12 +5333,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr =
- DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
- /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
- /*RefersToEnclosingVariableOrCapture*/ false,
- DE->getLocStart(), DE->getType(),
- /*VK*/ VK_LValue);
+ auto VDPrivateRefExpr = buildDeclRefExpr(
+ *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc());
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
Vars.push_back(DE);
PrivateCopies.push_back(VDPrivateRefExpr);
@@ -4451,11 +5353,17 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> SrcExprs;
+ SmallVector<Expr *, 8> DstExprs;
+ SmallVector<Expr *, 8> AssignmentOps;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -4477,6 +5385,9 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -4521,6 +5432,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// lastprivate clause on a worksharing construct if any of the corresponding
// worksharing regions ever binds to any of the corresponding parallel
// regions.
+ DSAStackTy::DSAVarData TopDVar = DVar;
if (isOpenMPWorksharingDirective(CurrDir) &&
!isOpenMPParallelDirective(CurrDir)) {
DVar = DSAStack->getImplicitDSA(VD, true);
@@ -4540,65 +5452,39 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// lastprivate clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- while (Type.getNonReferenceType()->isArrayType())
- Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
- ->getElementType();
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual copying and destructing of the
- // lastprivate variable.
- if (RD) {
- CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
- DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (MD) {
- if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
- MD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 2;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, MD);
- DiagnoseUseOfDecl(MD, ELoc);
- }
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_lastprivate) << 4;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
- }
- }
+ Type = Context.getBaseElementType(Type).getNonReferenceType();
+ auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
+ Type.getUnqualifiedType(), ".lastprivate.src");
+ auto *PseudoSrcExpr = buildDeclRefExpr(
+ *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc());
+ auto *DstVD =
+ buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst");
+ auto *PseudoDstExpr =
+ buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
+ // For arrays generate assignment operation for single element and replace
+ // it by the original array element in CodeGen.
+ auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
+ if (AssignmentOp.isInvalid())
+ continue;
+ AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+ /*DiscardedValue=*/true);
+ if (AssignmentOp.isInvalid())
+ continue;
- if (DVar.CKind != OMPC_firstprivate)
+ if (TopDVar.CKind != OMPC_firstprivate)
DSAStack->addDSA(VD, DE, OMPC_lastprivate);
Vars.push_back(DE);
+ SrcExprs.push_back(PseudoSrcExpr);
+ DstExprs.push_back(PseudoDstExpr);
+ AssignmentOps.push_back(AssignmentOp.get());
}
if (Vars.empty())
return nullptr;
return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- Vars);
+ Vars, SrcExprs, DstExprs, AssignmentOps);
}
OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
@@ -4718,19 +5604,19 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
switch (OOK) {
case OO_Plus:
case OO_Minus:
- BOK = BO_AddAssign;
+ BOK = BO_Add;
break;
case OO_Star:
- BOK = BO_MulAssign;
+ BOK = BO_Mul;
break;
case OO_Amp:
- BOK = BO_AndAssign;
+ BOK = BO_And;
break;
case OO_Pipe:
- BOK = BO_OrAssign;
+ BOK = BO_Or;
break;
case OO_Caret:
- BOK = BO_XorAssign;
+ BOK = BO_Xor;
break;
case OO_AmpAmp:
BOK = BO_LAnd;
@@ -4738,7 +5624,44 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
case OO_PipePipe:
BOK = BO_LOr;
break;
- default:
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ case OO_Slash:
+ case OO_Percent:
+ case OO_Tilde:
+ case OO_Exclaim:
+ case OO_Equal:
+ case OO_Less:
+ case OO_Greater:
+ case OO_LessEqual:
+ case OO_GreaterEqual:
+ case OO_PlusEqual:
+ case OO_MinusEqual:
+ case OO_StarEqual:
+ case OO_SlashEqual:
+ case OO_PercentEqual:
+ case OO_CaretEqual:
+ case OO_AmpEqual:
+ case OO_PipeEqual:
+ case OO_LessLess:
+ case OO_GreaterGreater:
+ case OO_LessLessEqual:
+ case OO_GreaterGreaterEqual:
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ case OO_Comma:
+ case OO_ArrowStar:
+ case OO_Arrow:
+ case OO_Call:
+ case OO_Subscript:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("Unexpected reduction identifier");
+ case OO_None:
if (auto II = DN.getAsIdentifierInfo()) {
if (II->isStr("max"))
BOK = BO_GT;
@@ -4760,11 +5683,17 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
}
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> LHSs;
+ SmallVector<Expr *, 8> RHSs;
+ SmallVector<Expr *, 8> ReductionOps;
for (auto RefExpr : VarList) {
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ LHSs.push_back(nullptr);
+ RHSs.push_back(nullptr);
+ ReductionOps.push_back(nullptr);
continue;
}
@@ -4773,6 +5702,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
RefExpr->containsUnexpandedParameterPack()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ LHSs.push_back(nullptr);
+ RHSs.push_back(nullptr);
+ ReductionOps.push_back(nullptr);
continue;
}
@@ -4865,23 +5797,6 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
<< VD;
continue;
}
- bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
- getDiagnostics().setSuppressAllDiagnostics(true);
- ExprResult ReductionOp =
- BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
- RefExpr, RefExpr);
- getDiagnostics().setSuppressAllDiagnostics(Suppress);
- if (ReductionOp.isInvalid()) {
- Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
- << ReductionIdRange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
-
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
// Variables with the predetermined data-sharing attributes may not be
@@ -4924,55 +5839,160 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
continue;
}
}
-
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual constructing/destructing of
- // the reduction variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_reduction) << 0;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
+ Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
+ auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs");
+ auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName());
+ // Add initializer for private variable.
+ Expr *Init = nullptr;
+ switch (BOK) {
+ case BO_Add:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LOr:
+ // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
+ if (Type->isScalarType() || Type->isAnyComplexType()) {
+ Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get();
}
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_reduction) << 4;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
+ break;
+ case BO_Mul:
+ case BO_LAnd:
+ if (Type->isScalarType() || Type->isAnyComplexType()) {
+ // '*' and '&&' reduction ops - initializer is '1'.
+ Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get();
+ }
+ break;
+ case BO_And: {
+ // '&' reduction op - initializer is '~0'.
+ QualType OrigType = Type;
+ if (auto *ComplexTy = OrigType->getAs<ComplexType>()) {
+ Type = ComplexTy->getElementType();
+ }
+ if (Type->isRealFloatingType()) {
+ llvm::APFloat InitValue =
+ llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type),
+ /*isIEEE=*/true);
+ Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
+ Type, ELoc);
+ } else if (Type->isScalarType()) {
+ auto Size = Context.getTypeSize(Type);
+ QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
+ llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
+ Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
+ }
+ if (Init && OrigType->isAnyComplexType()) {
+ // Init = 0xFFFF + 0xFFFFi;
+ auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
+ Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
+ }
+ Type = OrigType;
+ break;
+ }
+ case BO_LT:
+ case BO_GT: {
+ // 'min' reduction op - initializer is 'Largest representable number in
+ // the reduction list item type'.
+ // 'max' reduction op - initializer is 'Least representable number in
+ // the reduction list item type'.
+ if (Type->isIntegerType() || Type->isPointerType()) {
+ bool IsSigned = Type->hasSignedIntegerRepresentation();
+ auto Size = Context.getTypeSize(Type);
+ QualType IntTy =
+ Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
+ llvm::APInt InitValue =
+ (BOK != BO_LT)
+ ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
+ : llvm::APInt::getMinValue(Size)
+ : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
+ : llvm::APInt::getMaxValue(Size);
+ Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
+ if (Type->isPointerType()) {
+ // Cast to pointer type.
+ auto CastExpr = BuildCStyleCastExpr(
+ SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc),
+ SourceLocation(), Init);
+ if (CastExpr.isInvalid())
+ continue;
+ Init = CastExpr.get();
}
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
+ } else if (Type->isRealFloatingType()) {
+ llvm::APFloat InitValue = llvm::APFloat::getLargest(
+ Context.getFloatTypeSemantics(Type), BOK != BO_LT);
+ Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
+ Type, ELoc);
}
+ break;
+ }
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_MulAssign:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ case BO_Assign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Comma:
+ llvm_unreachable("Unexpected reduction operation");
}
+ if (Init) {
+ AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
+ /*TypeMayContainAuto=*/false);
+ } else {
+ ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
+ }
+ if (!RHSVD->hasInit()) {
+ Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
+ << ReductionIdRange;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);
+ auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc);
+ ExprResult ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
+ LHSDRE, RHSDRE);
+ if (ReductionOp.isUsable()) {
+ if (BOK != BO_LT && BOK != BO_GT) {
+ ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
+ BO_Assign, LHSDRE, ReductionOp.get());
+ } else {
+ auto *ConditionalOp = new (Context) ConditionalOperator(
+ ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(),
+ RHSDRE, Type, VK_LValue, OK_Ordinary);
+ ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
+ BO_Assign, LHSDRE, ConditionalOp);
+ }
+ if (ReductionOp.isUsable()) {
+ ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
+ }
+ }
+ if (ReductionOp.isInvalid())
+ continue;
DSAStack->addDSA(VD, DE, OMPC_reduction);
Vars.push_back(DE);
+ LHSs.push_back(LHSDRE);
+ RHSs.push_back(RHSDRE);
+ ReductionOps.push_back(ReductionOp.get());
}
if (Vars.empty())
@@ -4980,7 +6000,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
return OMPReductionClause::Create(
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
- ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId);
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs,
+ RHSs, ReductionOps);
}
OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
@@ -4989,11 +6010,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
SourceLocation ColonLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> Inits;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Inits.push_back(nullptr);
continue;
}
@@ -5035,6 +6058,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
if (QType->isDependentType() || QType->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ Inits.push_back(nullptr);
continue;
}
@@ -5080,14 +6104,22 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
continue;
}
+ // Build var to save initial value.
+ VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start");
+ AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(),
+ /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+ auto InitRef = buildDeclRefExpr(
+ *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());
DSAStack->addDSA(VD, DE, OMPC_linear);
Vars.push_back(DE);
+ Inits.push_back(InitRef);
}
if (Vars.empty())
return nullptr;
Expr *StepExpr = Step;
+ Expr *CalcStepExpr = nullptr;
if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
!Step->isInstantiationDependent() &&
!Step->containsUnexpandedParameterPack()) {
@@ -5097,17 +6129,82 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
return nullptr;
StepExpr = Val.get();
+ // Build var to save the step value.
+ VarDecl *SaveVar =
+ buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
+ ExprResult SaveRef =
+ buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
+ ExprResult CalcStep =
+ BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
+
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
llvm::APSInt Result;
- if (StepExpr->isIntegerConstantExpr(Result, Context) &&
- !Result.isNegative() && !Result.isStrictlyPositive())
+ bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context);
+ if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive())
Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
<< (Vars.size() > 1);
+ if (!IsConstant && CalcStep.isUsable()) {
+ // Calculate the step beforehand instead of doing this on each iteration.
+ // (This is not used if the number of iterations may be kfold-ed).
+ CalcStepExpr = CalcStep.get();
+ }
}
return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
- Vars, StepExpr);
+ Vars, Inits, StepExpr, CalcStepExpr);
+}
+
+static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
+ Expr *NumIterations, Sema &SemaRef,
+ Scope *S) {
+ // Walk the vars and build update/final expressions for the CodeGen.
+ SmallVector<Expr *, 8> Updates;
+ SmallVector<Expr *, 8> Finals;
+ Expr *Step = Clause.getStep();
+ Expr *CalcStep = Clause.getCalcStep();
+ // OpenMP [2.14.3.7, linear clause]
+ // If linear-step is not specified it is assumed to be 1.
+ if (Step == nullptr)
+ Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
+ else if (CalcStep)
+ Step = cast<BinaryOperator>(CalcStep)->getLHS();
+ bool HasErrors = false;
+ auto CurInit = Clause.inits().begin();
+ for (auto &RefExpr : Clause.varlists()) {
+ Expr *InitExpr = *CurInit;
+
+ // Build privatized reference to the current linear var.
+ auto DE = cast<DeclRefExpr>(RefExpr);
+ auto PrivateRef =
+ buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
+ DE->getType().getUnqualifiedType(), DE->getExprLoc(),
+ /*RefersToCapture=*/true);
+
+ // Build update: Var = InitExpr + IV * Step
+ ExprResult Update =
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ InitExpr, IV, Step, /* Subtract */ false);
+ Update = SemaRef.ActOnFinishFullExpr(Update.get());
+
+ // Build final: Var = InitExpr + NumIterations * Step
+ ExprResult Final =
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ InitExpr, NumIterations, Step, /* Subtract */ false);
+ Final = SemaRef.ActOnFinishFullExpr(Final.get());
+ if (!Update.isUsable() || !Final.isUsable()) {
+ Updates.push_back(nullptr);
+ Finals.push_back(nullptr);
+ HasErrors = true;
+ } else {
+ Updates.push_back(Update.get());
+ Finals.push_back(Final.get());
+ }
+ ++CurInit;
+ }
+ Clause.setUpdates(Updates);
+ Clause.setFinals(Finals);
+ return HasErrors;
}
OMPClause *Sema::ActOnOpenMPAlignedClause(
@@ -5137,10 +6234,8 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
// OpenMP [2.8.1, simd construct, Restrictions]
// The type of list items appearing in the aligned clause must be
// array, pointer, reference to array, or reference to pointer.
- QualType QType = DE->getType()
- .getNonReferenceType()
- .getUnqualifiedType()
- .getCanonicalType();
+ QualType QType = VD->getType();
+ QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
const Type *Ty = QType.getTypePtrOrNull();
if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() &&
!Ty->isPointerType())) {
@@ -5190,11 +6285,17 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> SrcExprs;
+ SmallVector<Expr *, 8> DstExprs;
+ SmallVector<Expr *, 8> AssignmentOps;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP copyin clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5216,6 +6317,9 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5232,40 +6336,38 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD =
- getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- // FIXME This code must be replaced by actual assignment of the
- // threadprivate variable.
- if (RD) {
- CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
- DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (MD) {
- if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
- MD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_copyin) << 2;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, MD);
- DiagnoseUseOfDecl(MD, ELoc);
- }
- }
+ auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
+ auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
+ ElemType.getUnqualifiedType(), ".copyin.src");
+ auto *PseudoSrcExpr = buildDeclRefExpr(
+ *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
+ auto *DstVD =
+ buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst");
+ auto *PseudoDstExpr =
+ buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
+ // For arrays generate assignment operation for single element and replace
+ // it by the original array element in CodeGen.
+ auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
+ if (AssignmentOp.isInvalid())
+ continue;
+ AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+ /*DiscardedValue=*/true);
+ if (AssignmentOp.isInvalid())
+ continue;
DSAStack->addDSA(VD, DE, OMPC_copyin);
Vars.push_back(DE);
+ SrcExprs.push_back(PseudoSrcExpr);
+ DstExprs.push_back(PseudoDstExpr);
+ AssignmentOps.push_back(AssignmentOp.get());
}
if (Vars.empty())
return nullptr;
- return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+ return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
+ SrcExprs, DstExprs, AssignmentOps);
}
OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
@@ -5273,11 +6375,17 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> SrcExprs;
+ SmallVector<Expr *, 8> DstExprs;
+ SmallVector<Expr *, 8> AssignmentOps;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5299,6 +6407,9 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ SrcExprs.push_back(nullptr);
+ DstExprs.push_back(nullptr);
+ AssignmentOps.push_back(nullptr);
continue;
}
@@ -5307,8 +6418,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// private or firstprivate clause on the single construct.
if (!DSAStack->isThreadPrivate(VD)) {
auto DVar = DSAStack->getTopDSA(VD, false);
- if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
- !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
+ DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_copyprivate);
@@ -5331,45 +6442,54 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
}
}
+ // Variably modified types are not supported.
+ if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
+ Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
+ << getOpenMPClauseName(OMPC_copyprivate) << Type
+ << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
// OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD =
- getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- // FIXME This code must be replaced by actual assignment of the
- // threadprivate variable.
- if (RD) {
- CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
- DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
- if (MD) {
- if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
- MD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_copyprivate) << 2;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, MD);
- DiagnoseUseOfDecl(MD, ELoc);
- }
- }
+ Type = Context.getBaseElementType(Type).getUnqualifiedType();
+ auto *SrcVD =
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src");
+ auto *PseudoSrcExpr =
+ buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc());
+ auto *DstVD =
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst");
+ auto *PseudoDstExpr =
+ buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
+ auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
+ if (AssignmentOp.isInvalid())
+ continue;
+ AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+ /*DiscardedValue=*/true);
+ if (AssignmentOp.isInvalid())
+ continue;
// No need to mark vars as copyprivate, they are already threadprivate or
// implicitly private.
Vars.push_back(DE);
+ SrcExprs.push_back(PseudoSrcExpr);
+ DstExprs.push_back(PseudoDstExpr);
+ AssignmentOps.push_back(AssignmentOp.get());
}
if (Vars.empty())
return nullptr;
- return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+ return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ Vars, SrcExprs, DstExprs, AssignmentOps);
}
OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
@@ -5382,3 +6502,66 @@ OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
}
+OMPClause *
+Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+ if (DepKind == OMPC_DEPEND_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_DEPEND_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_DEPEND_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot appear
+ // in a depend clause.
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) ||
+ (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
+ DepLoc, ColonLoc, Vars);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 9195ee5..31f581d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -286,6 +286,16 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
QualType FromType = getToType(0);
QualType ToType = getToType(1);
switch (Second) {
+ // 'bool' is an integral type; dispatch to the right place to handle it.
+ case ICK_Boolean_Conversion:
+ if (FromType->isRealFloatingType())
+ goto FloatingIntegralConversion;
+ if (FromType->isIntegralOrUnscopedEnumerationType())
+ goto IntegralConversion;
+ // Boolean conversions can be from pointers and pointers to members
+ // [conv.bool], and those aren't considered narrowing conversions.
+ return NK_Not_Narrowing;
+
// -- from a floating-point type to an integer type, or
//
// -- from an integer type or unscoped enumeration type to a floating-point
@@ -293,6 +303,7 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
// value after conversion will fit into the target type and will produce
// the original value when converted back to the original type, or
case ICK_Floating_Integral:
+ FloatingIntegralConversion:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
} else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
@@ -357,13 +368,8 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
// the source is a constant expression and the actual value after
// conversion will fit into the target type and will produce the original
// value when converted back to the original type.
- case ICK_Boolean_Conversion: // Bools are integers too.
- if (!FromType->isIntegralOrUnscopedEnumerationType()) {
- // Boolean conversions can be from pointers and pointers to members
- // [conv.bool], and those aren't considered narrowing conversions.
- return NK_Not_Narrowing;
- } // Otherwise, fall through to the integral case.
- case ICK_Integral_Conversion: {
+ case ICK_Integral_Conversion:
+ IntegralConversion: {
assert(FromType->isIntegralOrUnscopedEnumerationType());
assert(ToType->isIntegralOrUnscopedEnumerationType());
const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
@@ -1098,11 +1104,11 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Attempt user-defined conversion.
OverloadCandidateSet Conversions(From->getExprLoc(),
OverloadCandidateSet::CSK_Normal);
- OverloadingResult UserDefResult
- = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
- AllowExplicit, AllowObjCConversionOnExplicit);
-
- if (UserDefResult == OR_Success) {
+ switch (IsUserDefinedConversion(S, From, ToType, ICS.UserDefined,
+ Conversions, AllowExplicit,
+ AllowObjCConversionOnExplicit)) {
+ case OR_Success:
+ case OR_Deleted:
ICS.setUserDefined();
ICS.UserDefined.Before.setAsIdentityConversion();
// C++ [over.ics.user]p4:
@@ -1131,7 +1137,9 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ICS.Standard.Second = ICK_Derived_To_Base;
}
}
- } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
+ break;
+
+ case OR_Ambiguous:
ICS.setAmbiguous();
ICS.Ambiguous.setFromType(From->getType());
ICS.Ambiguous.setToType(ToType);
@@ -1139,8 +1147,12 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
Cand != Conversions.end(); ++Cand)
if (Cand->Viable)
ICS.Ambiguous.addConversion(Cand->Function);
- } else {
+ break;
+
+ // Fall through.
+ case OR_No_Viable_Function:
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+ break;
}
return ICS;
@@ -1740,18 +1752,20 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
return false;
// We can perform an integral promotion to the underlying type of the enum,
- // even if that's not the promoted type.
+ // even if that's not the promoted type. Note that the check for promoting
+ // the underlying type is based on the type alone, and does not consider
+ // the bitfield-ness of the actual source expression.
if (FromEnumType->getDecl()->isFixed()) {
QualType Underlying = FromEnumType->getDecl()->getIntegerType();
return Context.hasSameUnqualifiedType(Underlying, ToType) ||
- IsIntegralPromotion(From, Underlying, ToType);
+ IsIntegralPromotion(nullptr, Underlying, ToType);
}
// We have already pre-calculated the promotion type, so this is trivial.
if (ToType->isIntegerType() &&
!RequireCompleteType(From->getLocStart(), FromType, 0))
- return Context.hasSameUnqualifiedType(ToType,
- FromEnumType->getDecl()->getPromotionType());
+ return Context.hasSameUnqualifiedType(
+ ToType, FromEnumType->getDecl()->getPromotionType());
}
// C++0x [conv.prom]p2:
@@ -1799,13 +1813,12 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// other value of that type for promotion purposes (C++ 4.5p3).
// FIXME: We should delay checking of bit-fields until we actually perform the
// conversion.
- using llvm::APSInt;
- if (From)
+ if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
- APSInt BitWidth;
+ llvm::APSInt BitWidth;
if (FromType->isIntegralType(Context) &&
MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
- APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
+ llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
ToSize = Context.getTypeSize(ToType);
// Are we promoting to an int from a bitfield that fits in an int?
@@ -1823,6 +1836,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
return false;
}
}
+ }
// An rvalue of type bool can be converted to an rvalue of type int,
// with false becoming zero and true becoming one (C++ 4.5p4).
@@ -2138,23 +2152,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
FromObjCPtr->getPointeeType()))
return false;
- // Check for compatible
- // Objective C++: We're able to convert between "id" or "Class" and a
- // pointer to any interface (in both directions).
- if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
- ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
- return true;
- }
- // Conversions with Objective-C's id<...>.
- if ((FromObjCPtr->isObjCQualifiedIdType() ||
- ToObjCPtr->isObjCQualifiedIdType()) &&
- Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
- /*compare=*/false)) {
- ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
- return true;
- }
- // Objective C++: We're able to convert from a pointer to an
- // interface to a pointer to a different interface.
+ // Conversion between Objective-C pointers.
if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType();
const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType();
@@ -2940,7 +2938,10 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+ switch (auto Result =
+ CandidateSet.BestViableFunction(S, From->getLocStart(),
+ Best, true)) {
+ case OR_Deleted:
case OR_Success: {
// Record the standard conversion we used and the conversion function.
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
@@ -2953,13 +2954,11 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
- return OR_Success;
+ return Result;
}
case OR_No_Viable_Function:
return OR_No_Viable_Function;
- case OR_Deleted:
- return OR_Deleted;
case OR_Ambiguous:
return OR_Ambiguous;
}
@@ -3093,11 +3092,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = FromRecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions = FromRecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
DeclAccessPair FoundDecl = I.getPair();
NamedDecl *D = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
@@ -3129,8 +3125,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+ switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(),
+ Best, true)) {
case OR_Success:
+ case OR_Deleted:
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
@@ -3158,7 +3156,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
- return OR_Success;
+ return Result;
}
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
@@ -3184,15 +3182,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// user-defined conversion sequence (see 13.3.3 and
// 13.3.3.1).
User.After = Best->FinalConversion;
- return OR_Success;
+ return Result;
}
llvm_unreachable("Not a constructor or conversion function?");
case OR_No_Viable_Function:
return OR_No_Viable_Function;
- case OR_Deleted:
- // No conversion here! We're done.
- return OR_Deleted;
case OR_Ambiguous:
return OR_Ambiguous;
@@ -3329,7 +3324,26 @@ CompareImplicitConversionSequences(Sema &S,
// Two implicit conversion sequences of the same form are
// indistinguishable conversion sequences unless one of the
// following rules apply: (C++ 13.3.3.2p3):
+
+ // List-initialization sequence L1 is a better conversion sequence than
+ // list-initialization sequence L2 if:
+ // - L1 converts to std::initializer_list<X> for some X and L2 does not, or,
+ // if not that,
+ // - L1 converts to type "array of N1 T", L2 converts to type "array of N2 T",
+ // and N1 is smaller than N2.,
+ // even if one of the other rules in this paragraph would otherwise apply.
+ if (!ICS1.isBad()) {
+ if (ICS1.isStdInitializerListElement() &&
+ !ICS2.isStdInitializerListElement())
+ return ImplicitConversionSequence::Better;
+ if (!ICS1.isStdInitializerListElement() &&
+ ICS2.isStdInitializerListElement())
+ return ImplicitConversionSequence::Worse;
+ }
+
if (ICS1.isStandard())
+ // Standard conversion sequence S1 is a better conversion sequence than
+ // standard conversion sequence S2 if [...]
Result = CompareStandardConversionSequences(S,
ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
@@ -3350,19 +3364,6 @@ CompareImplicitConversionSequences(Sema &S,
ICS2.UserDefined.ConversionFunction);
}
- // List-initialization sequence L1 is a better conversion sequence than
- // list-initialization sequence L2 if L1 converts to std::initializer_list<X>
- // for some X and L2 does not.
- if (Result == ImplicitConversionSequence::Indistinguishable &&
- !ICS1.isBad()) {
- if (ICS1.isStdInitializerListElement() &&
- !ICS2.isStdInitializerListElement())
- return ImplicitConversionSequence::Better;
- if (!ICS1.isStdInitializerListElement() &&
- ICS2.isStdInitializerListElement())
- return ImplicitConversionSequence::Worse;
- }
-
return Result;
}
@@ -4034,11 +4035,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal);
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = T2RecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4254,16 +4252,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// -- Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference.
- //
- // We actually handle one oddity of C++ [over.ics.ref] at this
- // point, which is that, due to p2 (which short-circuits reference
- // binding by only attempting a simple conversion for non-direct
- // bindings) and p3's strange wording, we allow a const volatile
- // reference to bind to an rvalue. Hence the check for the presence
- // of "const" rather than checking for "const" being the only
- // qualifier.
- // This is also the point where rvalue references and lvalue inits no longer
- // go together.
if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified()))
return ICS;
@@ -4456,11 +4444,57 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
if (S.RequireCompleteType(From->getLocStart(), ToType, 0))
return Result;
+ // Per DR1467:
+ // If the parameter type is a class X and the initializer list has a single
+ // element of type cv U, where U is X or a class derived from X, the
+ // implicit conversion sequence is the one required to convert the element
+ // to the parameter type.
+ //
+ // Otherwise, if the parameter type is a character array [... ]
+ // and the initializer list has a single element that is an
+ // appropriately-typed string literal (8.5.2 [dcl.init.string]), the
+ // implicit conversion sequence is the identity conversion.
+ if (From->getNumInits() == 1) {
+ if (ToType->isRecordType()) {
+ QualType InitType = From->getInit(0)->getType();
+ if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
+ S.IsDerivedFrom(InitType, ToType))
+ return TryCopyInitialization(S, From->getInit(0), ToType,
+ SuppressUserConversions,
+ InOverloadResolution,
+ AllowObjCWritebackConversion);
+ }
+ // FIXME: Check the other conditions here: array of character type,
+ // initializer is a string literal.
+ if (ToType->isArrayType()) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(S.Context, ToType,
+ /*Consumed=*/false);
+ if (S.CanPerformCopyInitialization(Entity, From)) {
+ Result.setStandard();
+ Result.Standard.setAsIdentityConversion();
+ Result.Standard.setFromType(ToType);
+ Result.Standard.setAllToTypes(ToType);
+ return Result;
+ }
+ }
+ }
+
+ // C++14 [over.ics.list]p2: Otherwise, if the parameter type [...] (below).
// C++11 [over.ics.list]p2:
// If the parameter type is std::initializer_list<X> or "array of X" and
// all the elements can be implicitly converted to X, the implicit
// conversion sequence is the worst conversion necessary to convert an
// element of the list to X.
+ //
+ // C++14 [over.ics.list]p3:
+ // Otherwise, if the parameter type is "array of N X", if the initializer
+ // list has exactly N elements or if it has fewer than N elements and X is
+ // default-constructible, and if all the elements of the initializer list
+ // can be implicitly converted to X, the implicit conversion sequence is
+ // the worst conversion necessary to convert an element of the list to X.
+ //
+ // FIXME: We're missing a lot of these checks.
bool toStdInitializerList = false;
QualType X;
if (ToType->isArrayType())
@@ -4499,6 +4533,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
return Result;
}
+ // C++14 [over.ics.list]p4:
// C++11 [over.ics.list]p3:
// Otherwise, if the parameter is a non-aggregate class X and overload
// resolution chooses a single best constructor [...] the implicit
@@ -4514,6 +4549,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
/*AllowObjCConversionOnExplicit=*/false);
}
+ // C++14 [over.ics.list]p5:
// C++11 [over.ics.list]p4:
// Otherwise, if the parameter has an aggregate type which can be
// initialized from the initializer list [...] the implicit conversion
@@ -4540,6 +4576,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
return Result;
}
+ // C++14 [over.ics.list]p6:
// C++11 [over.ics.list]p5:
// Otherwise, if the parameter is a reference, see 13.3.3.1.4.
if (ToType->isReferenceType()) {
@@ -4608,14 +4645,15 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
return Result;
}
+ // C++14 [over.ics.list]p7:
// C++11 [over.ics.list]p6:
// Otherwise, if the parameter type is not a class:
if (!ToType->isRecordType()) {
- // - if the initializer list has one element, the implicit conversion
- // sequence is the one required to convert the element to the
- // parameter type.
+ // - if the initializer list has one element that is not itself an
+ // initializer list, the implicit conversion sequence is the one
+ // required to convert the element to the parameter type.
unsigned NumInits = From->getNumInits();
- if (NumInits == 1)
+ if (NumInits == 1 && !isa<InitListExpr>(From->getInit(0)))
Result = TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
@@ -4631,6 +4669,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
return Result;
}
+ // C++14 [over.ics.list]p8:
// C++11 [over.ics.list]p7:
// In all cases other than those enumerated above, no conversion is possible
return Result;
@@ -5347,21 +5386,18 @@ ExprResult Sema::PerformContextualImplicitConversion(
UnresolvedSet<4>
ViableConversions; // These are *potentially* viable in C++1y.
UnresolvedSet<4> ExplicitConversions;
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator> Conversions =
+ const auto &Conversions =
cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
bool HadMultipleCandidates =
- (std::distance(Conversions.first, Conversions.second) > 1);
+ (std::distance(Conversions.begin(), Conversions.end()) > 1);
// To check that there is only one target type, in C++1y:
QualType ToType;
bool HasUniqueTargetType = true;
// Collect explicit or viable (potentially in C++1y) conversions.
- for (CXXRecordDecl::conversion_iterator I = Conversions.first,
- E = Conversions.second;
- I != E; ++I) {
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
CXXConversionDecl *Conversion;
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
@@ -5554,7 +5590,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// is irrelevant.
AddMethodCandidate(Method, FoundDecl, Method->getParent(),
QualType(), Expr::Classification::makeSimpleLValue(),
- Args, CandidateSet, SuppressUserConversions);
+ Args, CandidateSet, SuppressUserConversions,
+ PartialOverloading);
return;
}
// We treat a constructor like a non-member function, since its object
@@ -5615,7 +5652,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if ((Args.size() + (PartialOverloading && Args.size())) > NumParams &&
+ if (TooManyArguments(NumParams, Args.size(), PartialOverloading) &&
!Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
@@ -5850,8 +5887,9 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
- TemplateArgumentListInfo *ExplicitTemplateArgs) {
+ bool PartialOverloading) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -5860,10 +5898,10 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args[0]->Classify(Context),
Args.slice(1), CandidateSet,
- SuppressUserConversions);
+ SuppressUserConversions, PartialOverloading);
else
AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
- SuppressUserConversions);
+ SuppressUserConversions, PartialOverloading);
} else {
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
@@ -5873,11 +5911,13 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ExplicitTemplateArgs,
Args[0]->getType(),
Args[0]->Classify(Context), Args.slice(1),
- CandidateSet, SuppressUserConversions);
+ CandidateSet, SuppressUserConversions,
+ PartialOverloading);
else
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
ExplicitTemplateArgs, Args,
- CandidateSet, SuppressUserConversions);
+ CandidateSet, SuppressUserConversions,
+ PartialOverloading);
}
}
}
@@ -5925,7 +5965,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
- bool SuppressUserConversions) {
+ bool SuppressUserConversions,
+ bool PartialOverloading) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -5958,7 +5999,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if (Args.size() > NumParams && !Proto->isVariadic()) {
+ if (TooManyArguments(NumParams, Args.size(), PartialOverloading) &&
+ !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
@@ -5970,7 +6012,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// parameter list is truncated on the right, so that there are
// exactly m parameters.
unsigned MinRequiredArgs = Method->getMinRequiredArguments();
- if (Args.size() < MinRequiredArgs) {
+ if (Args.size() < MinRequiredArgs && !PartialOverloading) {
// Not enough arguments.
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
@@ -6052,7 +6094,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions) {
+ bool SuppressUserConversions,
+ bool PartialOverloading) {
if (!CandidateSet.isNewCandidate(MethodTmpl))
return;
@@ -6069,7 +6112,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
- Specialization, Info)) {
+ Specialization, Info, PartialOverloading)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = MethodTmpl->getTemplatedDecl();
@@ -6090,7 +6133,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification, Args,
- CandidateSet, SuppressUserConversions);
+ CandidateSet, SuppressUserConversions, PartialOverloading);
}
/// \brief Add a C++ function template specialization as a candidate
@@ -6102,7 +6145,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions) {
+ bool SuppressUserConversions,
+ bool PartialOverloading) {
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
@@ -6119,7 +6163,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
- Specialization, Info)) {
+ Specialization, Info, PartialOverloading)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
@@ -6137,7 +6181,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
- SuppressUserConversions);
+ SuppressUserConversions, PartialOverloading);
}
/// Determine whether this is an allowable conversion from the result
@@ -6884,12 +6928,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = ClassDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
- NamedDecl *D = I.getDecl();
+ for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -6953,13 +6992,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
if (!ClassDecl->hasDefinition())
return VRQuals;
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = ClassDecl->getVisibleConversionFunctions();
-
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
- NamedDecl *D = I.getDecl();
+ for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) {
@@ -8078,7 +8111,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
bool HasArithmeticOrEnumeralCandidateType = false;
SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- CandidateTypes.push_back(BuiltinCandidateTypeSet(*this));
+ CandidateTypes.emplace_back(*this);
CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
OpLoc,
true,
@@ -8291,7 +8324,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
} else
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
FoundDecl, ExplicitTemplateArgs,
- Args, CandidateSet);
+ Args, CandidateSet, PartialOverloading);
}
}
@@ -9451,10 +9484,7 @@ struct CompareOverloadCandidatesForDisplay {
numLFixes = (numLFixes == 0) ? UINT_MAX : numLFixes;
numRFixes = (numRFixes == 0) ? UINT_MAX : numRFixes;
if (numLFixes != numRFixes) {
- if (numLFixes < numRFixes)
- return true;
- else
- return false;
+ return numLFixes < numRFixes;
}
// If there's any ordering between the defined conversions...
@@ -10363,7 +10393,8 @@ static void AddOverloadedCallCandidate(Sema &S,
assert(!KnownValid && "Explicit template arguments?");
return;
}
- S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false,
+ S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
PartialOverloading);
return;
}
@@ -10371,7 +10402,9 @@ static void AddOverloadedCallCandidate(Sema &S,
if (FunctionTemplateDecl *FuncTemplate
= dyn_cast<FunctionTemplateDecl>(Callee)) {
S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
- ExplicitTemplateArgs, Args, CandidateSet);
+ ExplicitTemplateArgs, Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
+ PartialOverloading);
return;
}
@@ -10458,7 +10491,8 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
const CXXScopeSpec &SS, LookupResult &R,
OverloadCandidateSet::CandidateSetKind CSK,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args,
+ bool *DoDiagnoseEmptyLookup = nullptr) {
if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty())
return false;
@@ -10475,6 +10509,8 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
// Don't diagnose names we find in classes; we get much better
// diagnostics for these from DiagnoseEmptyLookup.
R.clear();
+ if (DoDiagnoseEmptyLookup)
+ *DoDiagnoseEmptyLookup = true;
return false;
}
@@ -10624,15 +10660,16 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
+ bool DoDiagnoseEmptyLookup = EmptyLookup;
if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
OverloadCandidateSet::CSK_Normal,
- ExplicitTemplateArgs, Args) &&
- (!EmptyLookup ||
- SemaRef.DiagnoseEmptyLookup(
- S, SS, R,
- MakeValidator(SemaRef, dyn_cast<MemberExpr>(Fn), Args.size(),
- ExplicitTemplateArgs != nullptr, AllowTypoCorrection),
- ExplicitTemplateArgs, Args)))
+ ExplicitTemplateArgs, Args,
+ &DoDiagnoseEmptyLookup) &&
+ (!DoDiagnoseEmptyLookup || SemaRef.DiagnoseEmptyLookup(
+ S, SS, R,
+ MakeValidator(SemaRef, dyn_cast<MemberExpr>(Fn), Args.size(),
+ ExplicitTemplateArgs != nullptr, AllowTypoCorrection),
+ ExplicitTemplateArgs, Args)))
return ExprError();
assert(!R.empty() && "lookup results empty despite recovery");
@@ -10697,26 +10734,29 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// functions, including those from argument-dependent lookup.
AddOverloadedCallCandidates(ULE, Args, *CandidateSet);
- // If we found nothing, try to recover.
- // BuildRecoveryCallExpr diagnoses the error itself, so we just bail
- // out if it fails.
- if (CandidateSet->empty()) {
- // In Microsoft mode, if we are inside a template class member function then
- // create a type dependent CallExpr. The goal is to postpone name lookup
- // to instantiation time to be able to search into type dependent base
- // classes.
- if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
- (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
- CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
- Context.DependentTy, VK_RValue,
- RParenLoc);
+ if (getLangOpts().MSVCCompat &&
+ CurContext->isDependentContext() && !isSFINAEContext() &&
+ (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
+
+ OverloadCandidateSet::iterator Best;
+ if (CandidateSet->empty() ||
+ CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best) ==
+ OR_No_Viable_Function) {
+ // In Microsoft mode, if we are inside a template class member function then
+ // create a type dependent CallExpr. The goal is to postpone name lookup
+ // to instantiation time to be able to search into type dependent base
+ // classes.
+ CallExpr *CE = new (Context) CallExpr(
+ Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc);
CE->setTypeDependent(true);
*Result = CE;
return true;
}
- return false;
}
+ if (CandidateSet->empty())
+ return false;
+
UnbridgedCasts.restore();
return false;
}
@@ -10896,7 +10936,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
- AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false);
+ AddFunctionCandidates(Fns, ArgsArray, CandidateSet);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
@@ -11105,7 +11145,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
- AddFunctionCandidates(Fns, Args, CandidateSet, false);
+ AddFunctionCandidates(Fns, Args, CandidateSet);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
@@ -11204,7 +11244,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Op == OO_Equal)
DiagnoseSelfMove(Args[0], Args[1], OpLoc);
- checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
+ checkCall(FnDecl, nullptr, ArgsArray, isa<CXXMethodDecl>(FnDecl), OpLoc,
TheCall->getSourceRange(), VariadicDoesNotApply);
return MaybeBindToTemporary(TheCall);
@@ -11546,6 +11586,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
return MaybeBindToTemporary(call);
}
+ if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
+ return new (Context)
+ CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc);
+
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
@@ -11805,11 +11849,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator> Conversions
- = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions =
+ cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -12154,8 +12196,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
OverloadCandidateSet CandidateSet(UDSuffixLoc,
OverloadCandidateSet::CSK_Normal);
- AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
- TemplateArgs);
+ AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, TemplateArgs,
+ /*SuppressUserConversions=*/true);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -12440,15 +12482,11 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
type = Context.BoundMemberTy;
}
- MemberExpr *ME = MemberExpr::Create(Context, Base,
- MemExpr->isArrow(),
- MemExpr->getQualifierLoc(),
- MemExpr->getTemplateKeywordLoc(),
- Fn,
- Found,
- MemExpr->getMemberNameInfo(),
- TemplateArgs,
- type, valueKind, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::Create(
+ Context, Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(),
+ MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found,
+ MemExpr->getMemberNameInfo(), TemplateArgs, type, valueKind,
+ OK_Ordinary);
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
return ME;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index 5e92d5d..fec9748 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -689,15 +689,7 @@ ExprResult ObjCPropertyOpBuilder::buildGet() {
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingGetter();
- QualType receiverType;
- if (RefExpr->isClassReceiver()) {
- receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
- } else if (RefExpr->isSuperReceiver()) {
- receiverType = RefExpr->getSuperReceiverType();
- } else {
- assert(InstanceReceiver);
- receiverType = InstanceReceiver->getType();
- }
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
if (!Getter->isImplicit())
S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
// Build a message-send.
@@ -730,21 +722,17 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingSetter();
- QualType receiverType;
- if (RefExpr->isClassReceiver()) {
- receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
- } else if (RefExpr->isSuperReceiver()) {
- receiverType = RefExpr->getSuperReceiverType();
- } else {
- assert(InstanceReceiver);
- receiverType = InstanceReceiver->getType();
- }
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
// Use assignment constraints when possible; they give us better
// diagnostics. "When possible" basically means anything except a
// C++ class type.
if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
- QualType paramType = (*Setter->param_begin())->getType();
+ QualType paramType = (*Setter->param_begin())->getType()
+ .substObjCMemberType(
+ receiverType,
+ Setter->getDeclContext(),
+ ObjCSubstitutionContext::Parameter);
if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
ExprResult opResult = op;
Sema::AssignConvertType assignResult
@@ -819,7 +807,9 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
// As a special case, if the method returns 'id', try to get
// a better type from the property.
if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
- QualType propType = RefExpr->getExplicitProperty()->getType();
+ QualType receiverType = RefExpr->getReceiverType(S.Context);
+ QualType propType = RefExpr->getExplicitProperty()
+ ->getUsageType(receiverType);
if (result.get()->getType()->isObjCIdType()) {
if (const ObjCObjectPointerType *ptr
= propType->getAs<ObjCObjectPointerType>()) {
@@ -1051,17 +1041,13 @@ Sema::ObjCSubscriptKind
// Look for a conversion to an integral, enumeration type, or
// objective-C pointer type.
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator> Conversions
- = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
-
int NoIntegrals=0, NoObjCIdPointers=0;
SmallVector<CXXConversionDecl *, 4> ConversionDecls;
-
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
- if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
+
+ for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
+ ->getVisibleConversionFunctions()) {
+ if (CXXConversionDecl *Conversion =
+ dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
QualType CT = Conversion->getConversionType().getNonReferenceType();
if (CT->isIntegralOrEnumerationType()) {
++NoIntegrals;
@@ -1123,9 +1109,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- ResultType->getAsObjCQualifiedInterfaceType())
- ResultType = iQFaceTy->getBaseType();
}
Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
@@ -1196,7 +1179,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
AtIndexGetter =
S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
RefExpr->getSourceRange(),
- true, false);
+ true);
}
if (AtIndexGetter) {
@@ -1232,9 +1215,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
if (const ObjCObjectPointerType *PTy =
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- ResultType->getAsObjCQualifiedInterfaceType())
- ResultType = iQFaceTy->getBaseType();
}
Sema::ObjCSubscriptKind Res =
@@ -1318,7 +1298,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
AtIndexSetter =
S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
RefExpr->getSourceRange(),
- true, false);
+ true);
}
bool err = false;
@@ -1446,7 +1426,7 @@ ExprResult MSPropertyOpBuilder::buildGet() {
ExprResult GetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- GetterName, nullptr, true);
+ GetterName, nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1476,7 +1456,7 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
ExprResult SetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- SetterName, nullptr, true);
+ SetterName, nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 1 /* setter */
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 0d1da45..c4f6fd8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
@@ -23,12 +24,15 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -236,7 +240,9 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- if (FD->hasAttr<WarnUnusedResultAttr>()) {
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
+ if (Func ? Func->hasUnusedResultAttr()
+ : FD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
@@ -265,10 +271,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
- if (MD->isPropertyAccessor()) {
- Diag(Loc, diag::warn_unused_property_expr);
- return;
- }
}
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm();
@@ -494,6 +496,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -648,12 +651,10 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
if (CondResult.isInvalid()) return StmtError();
Cond = CondResult.get();
- if (!CondVar) {
- CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
- if (CondResult.isInvalid())
- return StmtError();
- Cond = CondResult.get();
- }
+ CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
+ if (CondResult.isInvalid())
+ return StmtError();
+ Cond = CondResult.get();
getCurFunction()->setHasBranchIntoScope();
@@ -687,26 +688,39 @@ static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
}
}
+typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
+
/// Returns true if we should emit a diagnostic about this case expression not
/// being a part of the enum used in the switch controlling expression.
-static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx,
+static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
const EnumDecl *ED,
- const Expr *CaseExpr) {
- // Don't warn if the 'case' expression refers to a static const variable of
- // the enum type.
- CaseExpr = CaseExpr->IgnoreParenImpCasts();
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) {
+ const Expr *CaseExpr,
+ EnumValsTy::iterator &EI,
+ EnumValsTy::iterator &EIEnd,
+ const llvm::APSInt &Val) {
+ bool FlagType = ED->hasAttr<FlagEnumAttr>();
+
+ if (const DeclRefExpr *DRE =
+ dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (!VD->hasGlobalStorage())
- return true;
QualType VarType = VD->getType();
- if (!VarType.isConstQualified())
- return true;
- QualType EnumType = Ctx.getTypeDeclType(ED);
- if (Ctx.hasSameUnqualifiedType(EnumType, VarType))
+ QualType EnumType = S.Context.getTypeDeclType(ED);
+ if (VD->hasGlobalStorage() && VarType.isConstQualified() &&
+ S.Context.hasSameUnqualifiedType(EnumType, VarType))
return false;
}
}
+
+ if (FlagType) {
+ return !S.IsValueInFlagEnum(ED, Val, false);
+ } else {
+ while (EI != EIEnd && EI->first < Val)
+ EI++;
+
+ if (EI != EIEnd && EI->first == Val)
+ return false;
+ }
+
return true;
}
@@ -897,12 +911,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
if (PrevString == CurrString)
Diag(CaseVals[i].second->getLHS()->getLocStart(),
diag::err_duplicate_case) <<
- (PrevString.empty() ? CaseValStr.str() : PrevString);
+ (PrevString.empty() ? StringRef(CaseValStr) : PrevString);
else
Diag(CaseVals[i].second->getLHS()->getLocStart(),
diag::err_duplicate_case_differing_expr) <<
- (PrevString.empty() ? CaseValStr.str() : PrevString) <<
- (CurrString.empty() ? CaseValStr.str() : CurrString) <<
+ (PrevString.empty() ? StringRef(CaseValStr) : PrevString) <<
+ (CurrString.empty() ? StringRef(CaseValStr) : CurrString) <<
CaseValStr;
Diag(CaseVals[i-1].second->getLHS()->getLocStart(),
@@ -1046,8 +1060,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If switch has default case, then ignore it.
if (!CaseListIsErroneous && !HasConstantCond && ET) {
const EnumDecl *ED = ET->getDecl();
- typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64>
- EnumValsTy;
EnumValsTy EnumVals;
// Gather all enum values, set their type and sort them,
@@ -1058,57 +1070,48 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
EnumVals.push_back(std::make_pair(Val, EDI));
}
std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
- EnumValsTy::iterator EIend =
+ auto EI = EnumVals.begin(), EIEnd =
std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
// See which case values aren't in enum.
- EnumValsTy::const_iterator EI = EnumVals.begin();
for (CaseValsTy::const_iterator CI = CaseVals.begin();
- CI != CaseVals.end(); CI++) {
- while (EI != EIend && EI->first < CI->first)
- EI++;
- if (EI == EIend || EI->first > CI->first) {
- Expr *CaseExpr = CI->second->getLHS();
- if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
- Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
- }
+ CI != CaseVals.end(); CI++) {
+ Expr *CaseExpr = CI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ CI->first))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
+
// See which of case ranges aren't in enum
EI = EnumVals.begin();
for (CaseRangesTy::const_iterator RI = CaseRanges.begin();
- RI != CaseRanges.end() && EI != EIend; RI++) {
- while (EI != EIend && EI->first < RI->first)
- EI++;
-
- if (EI == EIend || EI->first != RI->first) {
- Expr *CaseExpr = RI->second->getLHS();
- if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
- Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
- }
+ RI != CaseRanges.end(); RI++) {
+ Expr *CaseExpr = RI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ RI->first))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
llvm::APSInt Hi =
RI->second->getRHS()->EvaluateKnownConstInt(Context);
AdjustAPSInt(Hi, CondWidth, CondIsSigned);
- while (EI != EIend && EI->first < Hi)
- EI++;
- if (EI == EIend || EI->first != Hi) {
- Expr *CaseExpr = RI->second->getRHS();
- if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
- Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
- }
+
+ CaseExpr = RI->second->getRHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ Hi))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
// Check which enum vals aren't in switch
- CaseValsTy::const_iterator CI = CaseVals.begin();
- CaseRangesTy::const_iterator RI = CaseRanges.begin();
+ auto CI = CaseVals.begin();
+ auto RI = CaseRanges.begin();
bool hasCasesNotInSwitch = false;
SmallVector<DeclarationName,8> UnhandledNames;
- for (EI = EnumVals.begin(); EI != EIend; EI++){
+ for (EI = EnumVals.begin(); EI != EIEnd; EI++){
// Drop unneeded case values
while (CI != CaseVals.end() && CI->first < EI->first)
CI++;
@@ -1135,29 +1138,15 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);
// Produce a nice diagnostic if multiple values aren't handled.
- switch (UnhandledNames.size()) {
- case 0: break;
- case 1:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case1 : diag::warn_missing_case1)
- << UnhandledNames[0];
- break;
- case 2:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case2 : diag::warn_missing_case2)
- << UnhandledNames[0] << UnhandledNames[1];
- break;
- case 3:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_case3 : diag::warn_missing_case3)
- << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
- break;
- default:
- Diag(CondExpr->getExprLoc(), TheDefaultStmt
- ? diag::warn_def_missing_cases : diag::warn_missing_cases)
- << (unsigned)UnhandledNames.size()
- << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
- break;
+ if (!UnhandledNames.empty()) {
+ DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(),
+ TheDefaultStmt ? diag::warn_def_missing_case
+ : diag::warn_missing_case)
+ << (int)UnhandledNames.size();
+
+ for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3);
+ I != E; ++I)
+ DB << UnhandledNames[I];
}
if (!hasCasesNotInSwitch)
@@ -1195,30 +1184,37 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context);
AdjustAPSInt(RhsVal, DstWidth, DstIsSigned);
const EnumDecl *ED = ET->getDecl();
- typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
- EnumValsTy;
- EnumValsTy EnumVals;
-
- // Gather all enum values, set their type and sort them,
- // allowing easier comparison with rhs constant.
- for (auto *EDI : ED->enumerators()) {
- llvm::APSInt Val = EDI->getInitVal();
- AdjustAPSInt(Val, DstWidth, DstIsSigned);
- EnumVals.push_back(std::make_pair(Val, EDI));
- }
- if (EnumVals.empty())
- return;
- std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
- EnumValsTy::iterator EIend =
- std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
-
- // See which values aren't in the enum.
- EnumValsTy::const_iterator EI = EnumVals.begin();
- while (EI != EIend && EI->first < RhsVal)
- EI++;
- if (EI == EIend || EI->first != RhsVal) {
- Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
+
+ if (ED->hasAttr<FlagEnumAttr>()) {
+ if (!IsValueInFlagEnum(ED, RhsVal, true))
+ Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
<< DstType.getUnqualifiedType();
+ } else {
+ typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
+ EnumValsTy;
+ EnumValsTy EnumVals;
+
+ // Gather all enum values, set their type and sort them,
+ // allowing easier comparison with rhs constant.
+ for (auto *EDI : ED->enumerators()) {
+ llvm::APSInt Val = EDI->getInitVal();
+ AdjustAPSInt(Val, DstWidth, DstIsSigned);
+ EnumVals.push_back(std::make_pair(Val, EDI));
+ }
+ if (EnumVals.empty())
+ return;
+ std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+ EnumValsTy::iterator EIend =
+ std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+
+ // See which values aren't in the enum.
+ EnumValsTy::const_iterator EI = EnumVals.begin();
+ while (EI != EIend && EI->first < RhsVal)
+ EI++;
+ if (EI == EIend || EI->first != RhsVal) {
+ Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
+ << DstType.getUnqualifiedType();
+ }
}
}
}
@@ -1233,6 +1229,7 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), WhileLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -1638,6 +1635,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
if (secondVar) {
ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
+ SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc);
if (SecondResult.isInvalid())
return StmtError();
}
@@ -1832,6 +1830,15 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
/// \return true if an error occurs.
static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
SourceLocation Loc, int DiagID) {
+ if (Decl->getType()->isUndeducedType()) {
+ ExprResult Res = SemaRef.CorrectDelayedTyposInExpr(Init);
+ if (!Res.isUsable()) {
+ Decl->setInvalidDecl();
+ return true;
+ }
+ Init = Res.get();
+ }
+
// Deduce the type for the iterator variable now rather than leaving it to
// AddInitializerToDecl, so we can produce a more suitable diagnostic.
QualType InitType;
@@ -2368,6 +2375,156 @@ StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) {
return S;
}
+// Warn when the loop variable is a const reference that creates a copy.
+// Suggest using the non-reference type for copies. If a copy can be prevented
+// suggest the const reference type that would do so.
+// For instance, given "for (const &Foo : Range)", suggest
+// "for (const Foo : Range)" to denote a copy is made for the loop. If
+// possible, also suggest "for (const &Bar : Range)" if this type prevents
+// the copy altogether.
+static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
+ const VarDecl *VD,
+ QualType RangeInitType) {
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ const MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(InitExpr);
+
+ // No copy made.
+ if (!MTE)
+ return;
+
+ const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts();
+
+ // Searching for either UnaryOperator for dereference of a pointer or
+ // CXXOperatorCallExpr for handling iterators.
+ while (!isa<CXXOperatorCallExpr>(E) && !isa<UnaryOperator>(E)) {
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(E)) {
+ E = CCE->getArg(0);
+ } else if (const CXXMemberCallExpr *Call = dyn_cast<CXXMemberCallExpr>(E)) {
+ const MemberExpr *ME = cast<MemberExpr>(Call->getCallee());
+ E = ME->getBase();
+ } else {
+ const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
+ E = MTE->GetTemporaryExpr();
+ }
+ E = E->IgnoreImpCasts();
+ }
+
+ bool ReturnsReference = false;
+ if (isa<UnaryOperator>(E)) {
+ ReturnsReference = true;
+ } else {
+ const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E);
+ const FunctionDecl *FD = Call->getDirectCallee();
+ QualType ReturnType = FD->getReturnType();
+ ReturnsReference = ReturnType->isReferenceType();
+ }
+
+ if (ReturnsReference) {
+ // Loop variable creates a temporary. Suggest either to go with
+ // non-reference loop variable to indiciate a copy is made, or
+ // the correct time to bind a const reference.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy)
+ << VD << VariableType << E->getType();
+ QualType NonReferenceType = VariableType.getNonReferenceType();
+ NonReferenceType.removeLocalConst();
+ QualType NewReferenceType =
+ SemaRef.Context.getLValueReferenceType(E->getType().withConst());
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference)
+ << NonReferenceType << NewReferenceType << VD->getSourceRange();
+ } else {
+ // The range always returns a copy, so a temporary is always created.
+ // Suggest removing the reference from the loop variable.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy)
+ << VD << RangeInitType;
+ QualType NonReferenceType = VariableType.getNonReferenceType();
+ NonReferenceType.removeLocalConst();
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type)
+ << NonReferenceType << VD->getSourceRange();
+ }
+}
+
+// Warns when the loop variable can be changed to a reference type to
+// prevent a copy. For instance, if given "for (const Foo x : Range)" suggest
+// "for (const Foo &x : Range)" if this form does not make a copy.
+static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
+ const VarDecl *VD) {
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
+ if (!CE->getConstructor()->isCopyConstructor())
+ return;
+ } else if (const CastExpr *CE = dyn_cast<CastExpr>(InitExpr)) {
+ if (CE->getCastKind() != CK_LValueToRValue)
+ return;
+ } else {
+ return;
+ }
+
+ // TODO: Determine a maximum size that a POD type can be before a diagnostic
+ // should be emitted. Also, only ignore POD types with trivial copy
+ // constructors.
+ if (VariableType.isPODType(SemaRef.Context))
+ return;
+
+ // Suggest changing from a const variable to a const reference variable
+ // if doing so will prevent a copy.
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)
+ << VD << VariableType << InitExpr->getType();
+ SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type)
+ << SemaRef.Context.getLValueReferenceType(VariableType)
+ << VD->getSourceRange();
+}
+
+/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
+/// 1) for (const foo &x : foos) where foos only returns a copy. Suggest
+/// using "const foo x" to show that a copy is made
+/// 2) for (const bar &x : foos) where bar is a temporary intialized by bar.
+/// Suggest either "const bar x" to keep the copying or "const foo& x" to
+/// prevent the copy.
+/// 3) for (const foo x : foos) where x is constructed from a reference foo.
+/// Suggest "const foo &x" to prevent the copy.
+static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
+ const CXXForRangeStmt *ForStmt) {
+ if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
+ ForStmt->getLocStart()) &&
+ SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
+ ForStmt->getLocStart()) &&
+ SemaRef.Diags.isIgnored(diag::warn_for_range_copy,
+ ForStmt->getLocStart())) {
+ return;
+ }
+
+ const VarDecl *VD = ForStmt->getLoopVariable();
+ if (!VD)
+ return;
+
+ QualType VariableType = VD->getType();
+
+ if (VariableType->isIncompleteType())
+ return;
+
+ const Expr *InitExpr = VD->getInit();
+ if (!InitExpr)
+ return;
+
+ if (VariableType->isReferenceType()) {
+ DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
+ ForStmt->getRangeInit()->getType());
+ } else if (VariableType.isConstQualified()) {
+ DiagnoseForRangeConstVariableCopies(SemaRef, VD);
+ }
+}
+
/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
/// This is a separate step from ActOnCXXForRangeStmt because analysis of the
/// body cannot be performed until after the type of the range variable is
@@ -2385,6 +2542,8 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B,
diag::warn_empty_range_based_for_body);
+ DiagnoseForRangeVariableCopies(*this, ForStmt);
+
return S;
}
@@ -2423,6 +2582,14 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
+static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc,
+ const Scope &DestScope) {
+ if (!S.CurrentSEHFinally.empty() &&
+ DestScope.Contains(*S.CurrentSEHFinally.back())) {
+ S.Diag(Loc, diag::warn_jump_out_of_seh_finally);
+ }
+}
+
StmtResult
Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
Scope *S = CurScope->getContinueParent();
@@ -2430,6 +2597,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
// C99 6.8.6.2p1: A break shall appear only in or as a loop body.
return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
}
+ CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S);
return new (Context) ContinueStmt(ContinueLoc);
}
@@ -2444,6 +2612,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
if (S->isOpenMPLoopScope())
return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt)
<< "break");
+ CheckJumpOutOfSEHFinally(*this, BreakLoc, *S);
return new (Context) BreakStmt(BreakLoc);
}
@@ -2903,6 +3072,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
CurScope->setNoNRVO();
}
+ CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
+
return R;
}
@@ -3179,7 +3350,7 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";
if (!Throw) {
- // @throw without an expression designates a rethrow (which much occur
+ // @throw without an expression designates a rethrow (which must occur
// in the context of an @catch clause).
Scope *AtCatchParent = CurScope;
while (AtCatchParent && !AtCatchParent->isAtCatchScope())
@@ -3251,35 +3422,112 @@ Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
}
namespace {
+class CatchHandlerType {
+ QualType QT;
+ unsigned IsPointer : 1;
-class TypeWithHandler {
- QualType t;
- CXXCatchStmt *stmt;
-public:
- TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
- : t(type), stmt(statement) {}
+ // This is a special constructor to be used only with DenseMapInfo's
+ // getEmptyKey() and getTombstoneKey() functions.
+ friend struct llvm::DenseMapInfo<CatchHandlerType>;
+ enum Unique { ForDenseMap };
+ CatchHandlerType(QualType QT, Unique) : QT(QT), IsPointer(false) {}
- // An arbitrary order is fine as long as it places identical
- // types next to each other.
- bool operator<(const TypeWithHandler &y) const {
- if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
- return true;
- if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
+public:
+ /// Used when creating a CatchHandlerType from a handler type; will determine
+ /// whether the type is a pointer or reference and will strip off the top
+ /// level pointer and cv-qualifiers.
+ CatchHandlerType(QualType Q) : QT(Q), IsPointer(false) {
+ if (QT->isPointerType())
+ IsPointer = true;
+
+ if (IsPointer || QT->isReferenceType())
+ QT = QT->getPointeeType();
+ QT = QT.getUnqualifiedType();
+ }
+
+ /// Used when creating a CatchHandlerType from a base class type; pretends the
+ /// type passed in had the pointer qualifier, does not need to get an
+ /// unqualified type.
+ CatchHandlerType(QualType QT, bool IsPointer)
+ : QT(QT), IsPointer(IsPointer) {}
+
+ QualType underlying() const { return QT; }
+ bool isPointer() const { return IsPointer; }
+
+ friend bool operator==(const CatchHandlerType &LHS,
+ const CatchHandlerType &RHS) {
+ // If the pointer qualification does not match, we can return early.
+ if (LHS.IsPointer != RHS.IsPointer)
return false;
- else
- return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
+ // Otherwise, check the underlying type without cv-qualifiers.
+ return LHS.QT == RHS.QT;
}
+};
+} // namespace
- bool operator==(const TypeWithHandler& other) const {
- return t == other.t;
+namespace llvm {
+template <> struct DenseMapInfo<CatchHandlerType> {
+ static CatchHandlerType getEmptyKey() {
+ return CatchHandlerType(DenseMapInfo<QualType>::getEmptyKey(),
+ CatchHandlerType::ForDenseMap);
}
- CXXCatchStmt *getCatchStmt() const { return stmt; }
- SourceLocation getTypeSpecStartLoc() const {
- return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+ static CatchHandlerType getTombstoneKey() {
+ return CatchHandlerType(DenseMapInfo<QualType>::getTombstoneKey(),
+ CatchHandlerType::ForDenseMap);
+ }
+
+ static unsigned getHashValue(const CatchHandlerType &Base) {
+ return DenseMapInfo<QualType>::getHashValue(Base.underlying());
+ }
+
+ static bool isEqual(const CatchHandlerType &LHS,
+ const CatchHandlerType &RHS) {
+ return LHS == RHS;
}
};
+// It's OK to treat CatchHandlerType as a POD type.
+template <> struct isPodLike<CatchHandlerType> {
+ static const bool value = true;
+};
+}
+
+namespace {
+class CatchTypePublicBases {
+ ASTContext &Ctx;
+ const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &TypesToCheck;
+ const bool CheckAgainstPointer;
+
+ CXXCatchStmt *FoundHandler;
+ CanQualType FoundHandlerType;
+
+public:
+ CatchTypePublicBases(
+ ASTContext &Ctx,
+ const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &T, bool C)
+ : Ctx(Ctx), TypesToCheck(T), CheckAgainstPointer(C),
+ FoundHandler(nullptr) {}
+
+ CXXCatchStmt *getFoundHandler() const { return FoundHandler; }
+ CanQualType getFoundHandlerType() const { return FoundHandlerType; }
+
+ static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &,
+ void *User) {
+ auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User);
+ if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {
+ CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer);
+ auto M = PBOT.TypesToCheck;
+ auto I = M.find(Check);
+ if (I != M.end()) {
+ PBOT.FoundHandler = I->second;
+ PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType());
+ return true;
+ }
+ }
+ return false;
+ }
+};
}
/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
@@ -3289,74 +3537,124 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// Don't report an error if 'try' is used in system headers.
if (!getLangOpts().CXXExceptions &&
!getSourceManager().isInSystemHeader(TryLoc))
- Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ Diag(TryLoc, diag::err_exceptions_disabled) << "try";
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
+ sema::FunctionScopeInfo *FSI = getCurFunction();
+
+ // C++ try is incompatible with SEH __try.
+ if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) {
+ Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
+ Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
+ }
+
const unsigned NumHandlers = Handlers.size();
- assert(NumHandlers > 0 &&
+ assert(!Handlers.empty() &&
"The parser shouldn't call this if there are no handlers.");
- SmallVector<TypeWithHandler, 8> TypesWithHandlers;
-
+ llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> HandledTypes;
for (unsigned i = 0; i < NumHandlers; ++i) {
- CXXCatchStmt *Handler = cast<CXXCatchStmt>(Handlers[i]);
- if (!Handler->getExceptionDecl()) {
- if (i < NumHandlers - 1)
- return StmtError(Diag(Handler->getLocStart(),
- diag::err_early_catch_all));
+ CXXCatchStmt *H = cast<CXXCatchStmt>(Handlers[i]);
+ // Diagnose when the handler is a catch-all handler, but it isn't the last
+ // handler for the try block. [except.handle]p5. Also, skip exception
+ // declarations that are invalid, since we can't usefully report on them.
+ if (!H->getExceptionDecl()) {
+ if (i < NumHandlers - 1)
+ return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all));
+ continue;
+ } else if (H->getExceptionDecl()->isInvalidDecl())
continue;
- }
-
- const QualType CaughtType = Handler->getCaughtType();
- const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
- TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
- }
-
- // Detect handlers for the same type as an earlier one.
- if (NumHandlers > 1) {
- llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
-
- TypeWithHandler prev = TypesWithHandlers[0];
- for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
- TypeWithHandler curr = TypesWithHandlers[i];
- if (curr == prev) {
- Diag(curr.getTypeSpecStartLoc(),
- diag::warn_exception_caught_by_earlier_handler)
- << curr.getCatchStmt()->getCaughtType().getAsString();
- Diag(prev.getTypeSpecStartLoc(),
- diag::note_previous_exception_handler)
- << prev.getCatchStmt()->getCaughtType().getAsString();
+ // Walk the type hierarchy to diagnose when this type has already been
+ // handled (duplication), or cannot be handled (derivation inversion). We
+ // ignore top-level cv-qualifiers, per [except.handle]p3
+ CatchHandlerType HandlerCHT =
+ (QualType)Context.getCanonicalType(H->getCaughtType());
+
+ // We can ignore whether the type is a reference or a pointer; we need the
+ // underlying declaration type in order to get at the underlying record
+ // decl, if there is one.
+ QualType Underlying = HandlerCHT.underlying();
+ if (auto *RD = Underlying->getAsCXXRecordDecl()) {
+ if (!RD->hasDefinition())
+ continue;
+ // Check that none of the public, unambiguous base classes are in the
+ // map ([except.handle]p1). Give the base classes the same pointer
+ // qualification as the original type we are basing off of. This allows
+ // comparison against the handler type using the same top-level pointer
+ // as the original type.
+ CXXBasePaths Paths;
+ Paths.setOrigin(RD);
+ CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer());
+ if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB,
+ Paths)) {
+ const CXXCatchStmt *Problem = CTPB.getFoundHandler();
+ if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) {
+ Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << H->getCaughtType();
+ Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << Problem->getCaughtType();
+ }
}
+ }
- prev = curr;
+ // Add the type the list of ones we have handled; diagnose if we've already
+ // handled it.
+ auto R = HandledTypes.insert(std::make_pair(H->getCaughtType(), H));
+ if (!R.second) {
+ const CXXCatchStmt *Problem = R.first->second;
+ Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << H->getCaughtType();
+ Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << Problem->getCaughtType();
}
}
- getCurFunction()->setHasBranchProtectedScope();
-
- // FIXME: We should detect handlers that cannot catch anything because an
- // earlier handler catches a superclass. Need to find a method that is not
- // quadratic for this.
- // Neither of these are explicitly forbidden, but every compiler detects them
- // and warns.
+ FSI->setHasCXXTry(TryLoc);
return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
}
-StmtResult
-Sema::ActOnSEHTryBlock(bool IsCXXTry,
- SourceLocation TryLoc,
- Stmt *TryBlock,
- Stmt *Handler) {
+StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
+ Stmt *TryBlock, Stmt *Handler) {
assert(TryBlock && Handler);
- getCurFunction()->setHasBranchProtectedScope();
+ sema::FunctionScopeInfo *FSI = getCurFunction();
+
+ // SEH __try is incompatible with C++ try. Borland appears to support this,
+ // however.
+ if (!getLangOpts().Borland) {
+ if (FSI->FirstCXXTryLoc.isValid()) {
+ Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
+ Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'";
+ }
+ }
+
+ FSI->setHasSEHTry(TryLoc);
+
+ // Reject __try in Obj-C methods, blocks, and captured decls, since we don't
+ // track if they use SEH.
+ DeclContext *DC = CurContext;
+ while (DC && !DC->isFunctionOrMethod())
+ DC = DC->getParent();
+ FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DC);
+ if (FD)
+ FD->setUsesSEHTry(true);
+ else
+ Diag(TryLoc, diag::err_seh_try_outside_functions);
- return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler);
+ // Reject __try on unsupported targets.
+ if (!Context.getTargetInfo().isSEHTrySupported())
+ Diag(TryLoc, diag::err_seh_try_unsupported);
+
+ return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
}
StmtResult
@@ -3374,11 +3672,18 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc,
return SEHExceptStmt::Create(Context,Loc,FilterExpr,Block);
}
-StmtResult
-Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
- Stmt *Block) {
+void Sema::ActOnStartSEHFinallyBlock() {
+ CurrentSEHFinally.push_back(CurScope);
+}
+
+void Sema::ActOnAbortSEHFinallyBlock() {
+ CurrentSEHFinally.pop_back();
+}
+
+StmtResult Sema::ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block) {
assert(Block);
- return SEHFinallyStmt::Create(Context,Loc,Block);
+ CurrentSEHFinally.pop_back();
+ return SEHFinallyStmt::Create(Context, Loc, Block);
}
StmtResult
@@ -3388,6 +3693,7 @@ Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) {
SEHTryParent = SEHTryParent->getParent();
if (!SEHTryParent)
return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));
+ CheckJumpOutOfSEHFinally(*this, Loc, *SEHTryParent);
return new (Context) SEHLeaveStmt(Loc);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index 0d32581..8e3e89f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
@@ -86,6 +87,11 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
WorkList.push_back(E);
while (WorkList.size()) {
Expr *E = WorkList.pop_back_val();
+ if (isa<CXXThisExpr>(E)) {
+ S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref);
+ S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
+ return true;
+ }
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (isa<ParmVarDecl>(DRE->getDecl())) {
S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
@@ -118,6 +124,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// The parser verifies that there is a string literal here.
assert(AsmString->isAscii());
+ bool ValidateConstraints =
+ DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl());
+
for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];
assert(Literal->isAscii());
@@ -127,7 +136,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
OutputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
- if (!Context.getTargetInfo().validateOutputConstraint(Info))
+ if (ValidateConstraints &&
+ !Context.getTargetInfo().validateOutputConstraint(Info))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_output_constraint)
<< Info.getConstraintStr());
@@ -144,6 +154,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
+ // Bitfield can't be referenced with a pointer.
+ if (Info.allowsMemory() && OutputExpr->refersToBitField())
+ return StmtError(Diag(OutputExpr->getLocStart(),
+ diag::err_asm_bitfield_in_memory_constraint)
+ << 1
+ << Info.getConstraintStr()
+ << OutputExpr->getSourceRange());
+
OutputConstraintInfos.push_back(Info);
// If this is dependent, just continue.
@@ -201,8 +219,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
InputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
- if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
- NumOutputs, Info)) {
+ if (ValidateConstraints &&
+ !Context.getTargetInfo().validateInputConstraint(
+ OutputConstraintInfos.data(), NumOutputs, Info)) {
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_input_constraint)
<< Info.getConstraintStr());
@@ -219,6 +238,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(InputExpr, *this))
return StmtError();
+ // Bitfield can't be referenced with a pointer.
+ if (Info.allowsMemory() && InputExpr->refersToBitField())
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_asm_bitfield_in_memory_constraint)
+ << 0
+ << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
if (CheckAsmLValue(InputExpr, *this))
@@ -227,17 +254,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
} else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
- llvm::APSInt Result;
- if (!InputExpr->EvaluateAsInt(Result, Context))
- return StmtError(
- Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
- << Info.getConstraintStr() << InputExpr->getSourceRange());
- if (Result.slt(Info.getImmConstantMin()) ||
- Result.sgt(Info.getImmConstantMax()))
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_invalid_asm_value_for_constraint)
- << Result.toString(10) << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ if (!InputExpr->isValueDependent()) {
+ llvm::APSInt Result;
+ if (!InputExpr->EvaluateAsInt(Result, Context))
+ return StmtError(
+ Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
+ << Info.getConstraintStr() << InputExpr->getSourceRange());
+ if (Result.slt(Info.getImmConstantMin()) ||
+ Result.sgt(Info.getImmConstantMax()))
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_invalid_asm_value_for_constraint)
+ << Result.toString(10) << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+ }
} else {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
@@ -307,32 +336,22 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (!Piece.isOperand()) continue;
// Look for the correct constraint index.
- unsigned Idx = 0;
- unsigned ConstraintIdx = 0;
- for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) {
- TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
- if (Idx == Piece.getOperandNo())
- break;
- ++Idx;
-
- if (Info.isReadWrite()) {
- if (Idx == Piece.getOperandNo())
- break;
- ++Idx;
- }
- }
+ unsigned ConstraintIdx = Piece.getOperandNo();
+ unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
- for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) {
- TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
- if (Idx == Piece.getOperandNo())
- break;
- ++Idx;
+ // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
+ // modifier '+'.
+ if (ConstraintIdx >= NumOperands) {
+ unsigned I = 0, E = NS->getNumOutputs();
- if (Info.isReadWrite()) {
- if (Idx == Piece.getOperandNo())
+ for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
+ if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
+ ConstraintIdx = I;
break;
- ++Idx;
- }
+ }
+
+ assert(I != E && "Invalid operand number should have been caught in "
+ " AnalyzeAsmString");
}
// Now that we have the right indexes go ahead and check.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index 19e2c8e..5b71c11 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -105,6 +105,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
if (StateLoc && StateLoc->Ident) {
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
+ else if (StateLoc->Ident->isStr("assume_safety"))
+ State = LoopHintAttr::AssumeSafety;
else
State = LoopHintAttr::Enable;
}
@@ -159,7 +161,7 @@ CheckForIncompatibleAttributes(Sema &S,
const LoopHintAttr *PrevAttr;
if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
- // Enable|disable hint. For example, vectorize(enable).
+ // Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
PrevAttr = CategoryState.StateAttr;
CategoryState.StateAttr = LH;
} else {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 1e71762..035c37c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -602,7 +602,7 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
return Param;
}
- Param->setDefaultArgument(DefaultTInfo, false);
+ Param->setDefaultArgument(DefaultTInfo);
}
return Param;
@@ -723,7 +723,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
}
Default = DefaultRes.get();
- Param->setDefaultArgument(Default, false);
+ Param->setDefaultArgument(Default);
}
return Param;
@@ -799,7 +799,7 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
UPPC_DefaultArgument))
return Param;
- Param->setDefaultArgument(DefaultArg, false);
+ Param->setDefaultArgument(Context, DefaultArg);
}
return Param;
@@ -836,7 +836,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc,
unsigned NumOuterTemplateParamLists,
- TemplateParameterList** OuterTemplateParamLists) {
+ TemplateParameterList** OuterTemplateParamLists,
+ SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
@@ -892,6 +893,16 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
LookupQualifiedName(Previous, SemanticContext);
} else {
SemanticContext = CurContext;
+
+ // C++14 [class.mem]p14:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // -- every member template of class T
+ if (TUK != TUK_Friend &&
+ DiagnoseClassNameShadow(SemanticContext,
+ DeclarationNameInfo(Name, NameLoc)))
+ return true;
+
LookupName(Previous, S);
}
@@ -946,8 +957,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check that the chosen semantic context doesn't already contain a
// declaration of this name as a non-tag type.
- LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
- ForRedeclaration);
+ Previous.clear(LookupOrdinaryName);
DeclContext *LookupContext = SemanticContext;
while (LookupContext->isTransparentContext())
LookupContext = LookupContext->getLookupParent();
@@ -961,9 +971,25 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
} else if (PrevDecl &&
- !isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid()))
+ !isDeclInScope(Previous.getRepresentativeDecl(), SemanticContext,
+ S, SS.isValid()))
PrevDecl = PrevClassTemplate = nullptr;
+ if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>(
+ PrevDecl ? Previous.getRepresentativeDecl() : nullptr)) {
+ if (SS.isEmpty() &&
+ !(PrevClassTemplate &&
+ PrevClassTemplate->getDeclContext()->getRedeclContext()->Equals(
+ SemanticContext->getRedeclContext()))) {
+ Diag(KWLoc, diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ // Recover by ignoring the old declaration.
+ PrevDecl = PrevClassTemplate = nullptr;
+ }
+ }
+
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
@@ -982,7 +1008,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// template declaration (7.1.5.3).
RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind,
- TUK == TUK_Definition, KWLoc, *Name)) {
+ TUK == TUK_Definition, KWLoc, Name)) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
@@ -993,6 +1019,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check for redefinition of this class template.
if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
+ // If we have a prior definition that is not visible, treat this as
+ // simply making that previous definition visible.
+ NamedDecl *Hidden = nullptr;
+ if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
+ SkipBody->ShouldSkip = true;
+ auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
+ assert(Tmpl && "original definition of a class template is not a "
+ "class template?");
+ makeMergedDefinitionVisible(Hidden, KWLoc);
+ makeMergedDefinitionVisible(Tmpl, KWLoc);
+ return Def;
+ }
+
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
@@ -1296,12 +1335,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
-
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
- } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
+ } else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) &&
NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
@@ -1311,8 +1349,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
- true);
+ NewTypeParm->setInheritedDefaultArgument(Context, OldTypeParm);
PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
} else if (NewTypeParm->hasDefaultArgument()) {
SawDefaultArgument = true;
@@ -1346,7 +1383,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
"Parameter packs can't have a default argument!");
if (!NewNonTypeParm->isPackExpansion())
SawParameterPack = true;
- } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
+ } else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) &&
NewNonTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
@@ -1356,12 +1393,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- // FIXME: We need to create a new kind of "default argument"
- // expression that points to a previous non-type template
- // parameter.
- NewNonTypeParm->setDefaultArgument(
- OldNonTypeParm->getDefaultArgument(),
- /*Inherited=*/ true);
+ NewNonTypeParm->setInheritedDefaultArgument(Context, OldNonTypeParm);
PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
} else if (NewNonTypeParm->hasDefaultArgument()) {
SawDefaultArgument = true;
@@ -1393,8 +1425,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
"Parameter packs can't have a default argument!");
if (!NewTemplateParm->isPackExpansion())
SawParameterPack = true;
- } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
- NewTemplateParm->hasDefaultArgument()) {
+ } else if (OldTemplateParm &&
+ hasVisibleDefaultArgument(OldTemplateParm) &&
+ NewTemplateParm->hasDefaultArgument()) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
SawDefaultArgument = true;
@@ -1403,11 +1436,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- // FIXME: We need to create a new kind of "default argument" expression
- // that points to a previous template template parameter.
- NewTemplateParm->setDefaultArgument(
- OldTemplateParm->getDefaultArgument(),
- /*Inherited=*/ true);
+ NewTemplateParm->setInheritedDefaultArgument(Context, OldTemplateParm);
PreviousDefaultArgLoc
= OldTemplateParm->getDefaultArgument().getLocation();
} else if (NewTemplateParm->hasDefaultArgument()) {
@@ -1798,7 +1827,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
}
} else if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
- if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
+ if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
ExpectedTemplateParams = Template->getTemplateParameters();
NeedNonemptyTemplateHeader = true;
}
@@ -2281,7 +2310,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
assert(Id && "templated class must have an identifier");
if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
- TagLoc, *Id)) {
+ TagLoc, Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
<< Result
<< FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
@@ -3295,7 +3324,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
HasDefaultArg = false;
if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
- if (!TypeParm->hasDefaultArgument())
+ if (!hasVisibleDefaultArgument(TypeParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
@@ -3312,7 +3341,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (NonTypeTemplateParmDecl *NonTypeParm
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- if (!NonTypeParm->hasDefaultArgument())
+ if (!hasVisibleDefaultArgument(NonTypeParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
@@ -3330,7 +3359,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
TemplateTemplateParmDecl *TempTempParm
= cast<TemplateTemplateParmDecl>(Param);
- if (!TempTempParm->hasDefaultArgument())
+ if (!hasVisibleDefaultArgument(TempTempParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
@@ -3640,6 +3669,35 @@ static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
return None;
}
+/// Diagnose a missing template argument.
+template<typename TemplateParmDecl>
+static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
+ TemplateDecl *TD,
+ const TemplateParmDecl *D,
+ TemplateArgumentListInfo &Args) {
+ // Dig out the most recent declaration of the template parameter; there may be
+ // declarations of the template that are more recent than TD.
+ D = cast<TemplateParmDecl>(cast<TemplateDecl>(TD->getMostRecentDecl())
+ ->getTemplateParameters()
+ ->getParam(D->getIndex()));
+
+ // If there's a default argument that's not visible, diagnose that we're
+ // missing a module import.
+ llvm::SmallVector<Module*, 8> Modules;
+ if (D->hasDefaultArgument() && !S.hasVisibleDefaultArgument(D, &Modules)) {
+ S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD),
+ D->getDefaultArgumentLoc(), Modules,
+ Sema::MissingImportKind::DefaultArgument,
+ /*Recover*/ true);
+ return true;
+ }
+
+ // FIXME: If there's a more recent default argument that *is* visible,
+ // diagnose that it was declared too late.
+
+ return diagnoseArityMismatch(S, TD, Loc, Args);
+}
+
/// \brief Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@@ -3795,8 +3853,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// (when the template parameter was part of a nested template) into
// the default argument.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
- if (!TTP->hasDefaultArgument())
- return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs);
+ if (!hasVisibleDefaultArgument(TTP))
+ return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
+ NewArgs);
TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
Template,
@@ -3811,8 +3870,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgType);
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
- if (!NTTP->hasDefaultArgument())
- return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs);
+ if (!hasVisibleDefaultArgument(NTTP))
+ return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
+ NewArgs);
ExprResult E = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
@@ -3828,8 +3888,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
- if (!TempParm->hasDefaultArgument())
- return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs);
+ if (!hasVisibleDefaultArgument(TempParm))
+ return diagnoseMissingArgument(*this, TemplateLoc, Template, TempParm,
+ NewArgs);
NestedNameSpecifierLoc QualifierLoc;
TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
@@ -5835,11 +5896,13 @@ static bool CheckTemplateSpecializationScope(Sema &S,
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
- << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
- else
+ else if (isa<NamespaceDecl>(SpecializedContext)) {
+ int Diag = diag::err_template_spec_redecl_out_of_scope;
+ if (S.getLangOpts().MicrosoftExt)
+ Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
+ S.Diag(Loc, Diag) << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+ } else
llvm_unreachable("unexpected namespace context for specialization");
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
@@ -6036,7 +6099,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SourceLocation ModulePrivateLoc,
TemplateIdAnnotation &TemplateId,
AttributeList *Attr,
- MultiTemplateParamsArg TemplateParameterLists) {
+ MultiTemplateParamsArg
+ TemplateParameterLists,
+ SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
CXXScopeSpec &SS = TemplateId.SS;
@@ -6134,7 +6199,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, TUK == TUK_Definition, KWLoc,
- *ClassTemplate->getIdentifier())) {
+ ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
@@ -6347,7 +6412,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
- if (RecordDecl *Def = Specialization->getDefinition()) {
+ RecordDecl *Def = Specialization->getDefinition();
+ NamedDecl *Hidden = nullptr;
+ if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
+ SkipBody->ShouldSkip = true;
+ makeMergedDefinitionVisible(Hidden, KWLoc);
+ // From here on out, treat this as just a redeclaration.
+ TUK = TUK_Declaration;
+ } else if (Def) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition)
<< Context.getTypeDeclType(Specialization) << Range;
@@ -7163,7 +7235,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, /*isDefinition*/false, KWLoc,
- *ClassTemplate->getIdentifier())) {
+ ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
@@ -7177,9 +7249,27 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
- TemplateSpecializationKind TSK
- = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
- : TSK_ExplicitInstantiationDeclaration;
+ TemplateSpecializationKind TSK = ExternLoc.isInvalid()
+ ? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ // Check for dllexport class template instantiation declarations.
+ for (AttributeList *A = Attr; A; A = A->getNext()) {
+ if (A->getKind() == AttributeList::AT_DLLExport) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLoc(), diag::note_attribute);
+ break;
+ }
+ }
+
+ if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLocation(), diag::note_attribute);
+ }
+ }
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
@@ -7315,10 +7405,30 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Fix a TSK_ExplicitInstantiationDeclaration followed by a
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
- TSK == TSK_ExplicitInstantiationDefinition)
+ TSK == TSK_ExplicitInstantiationDefinition) {
// FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
+ if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // In the MS ABI, an explicit instantiation definition can add a dll
+ // attribute to a template with a previous instantiation declaration.
+ // MinGW doesn't allow this.
+ auto *A = cast<InheritableAttr>(
+ getDLLAttr(Specialization)->clone(getASTContext()));
+ A->setInherited(true);
+ Def->addAttr(A);
+ checkClassLevelDLLAttribute(Def);
+
+ // Propagate attribute to base class templates.
+ for (auto &B : Def->bases()) {
+ if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ B.getType()->getAsCXXRecordDecl()))
+ propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
+ }
+ }
+ }
+
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
}
@@ -8285,7 +8395,7 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
// Take tokens to avoid allocations
LPT->Toks.swap(Toks);
LPT->D = FnD;
- LateParsedTemplateMap[FD] = LPT;
+ LateParsedTemplateMap.insert(std::make_pair(FD, LPT));
FD->setLateTemplateParsed(true);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index dd2a4d2..ae8157e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -91,30 +91,6 @@ DeduceTemplateArguments(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced);
-/// \brief Whether template argument deduction for two reference parameters
-/// resulted in the argument type, parameter type, or neither type being more
-/// qualified than the other.
-enum DeductionQualifierComparison {
- NeitherMoreQualified = 0,
- ParamMoreQualified,
- ArgMoreQualified
-};
-
-/// \brief Stores the result of comparing two reference parameters while
-/// performing template argument deduction for partial ordering of function
-/// templates.
-struct RefParamPartialOrderingComparison {
- /// \brief Whether the parameter type is an rvalue reference type.
- bool ParamIsRvalueRef;
- /// \brief Whether the argument type is an rvalue reference type.
- bool ArgIsRvalueRef;
-
- /// \brief Whether the parameter or argument (or neither) is more qualified.
- DeductionQualifierComparison Qualifiers;
-};
-
-
-
static Sema::TemplateDeductionResult
DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateParameterList *TemplateParams,
@@ -124,9 +100,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &
Deduced,
unsigned TDF,
- bool PartialOrdering = false,
- SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = nullptr);
+ bool PartialOrdering = false);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
@@ -602,6 +576,7 @@ struct clang::DeducedPack {
DeducedPack *Outer;
};
+namespace {
/// A scope in which we're performing pack deduction.
class PackDeductionScope {
public:
@@ -756,6 +731,7 @@ private:
SmallVector<DeducedPack, 2> Packs;
};
+} // namespace
/// \brief Deduce the template arguments by comparing the list of parameter
/// types to the list of argument types, as in the parameter-type-lists of
@@ -784,9 +760,6 @@ private:
/// deduction for during partial ordering for a call
/// (C++0x [temp.deduct.partial]).
///
-/// \param RefParamComparisons If we're performing template argument deduction
-/// in the context of partial ordering, the set of qualifier comparisons.
-///
/// \returns the result of template argument deduction so far. Note that a
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
@@ -798,9 +771,7 @@ DeduceTemplateArguments(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
- bool PartialOrdering = false,
- SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = nullptr) {
+ bool PartialOrdering = false) {
// Fast-path check to see if we have too many/too few arguments.
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
@@ -836,8 +807,7 @@ DeduceTemplateArguments(Sema &S,
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
Params[ParamIdx], Args[ArgIdx],
Info, Deduced, TDF,
- PartialOrdering,
- RefParamComparisons))
+ PartialOrdering))
return Result;
++ArgIdx;
@@ -869,8 +839,7 @@ DeduceTemplateArguments(Sema &S,
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
Args[ArgIdx], Info, Deduced,
- TDF, PartialOrdering,
- RefParamComparisons))
+ TDF, PartialOrdering))
return Result;
PackScope.nextPackElement();
@@ -967,9 +936,6 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param,
/// \param PartialOrdering Whether we're performing template argument deduction
/// in the context of partial ordering (C++0x [temp.deduct.partial]).
///
-/// \param RefParamComparisons If we're performing template argument deduction
-/// in the context of partial ordering, the set of qualifier comparisons.
-///
/// \returns the result of template argument deduction so far. Note that a
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
@@ -980,9 +946,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
- bool PartialOrdering,
- SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons) {
+ bool PartialOrdering) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -995,7 +959,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Arg = ArgExpansion->getPattern();
if (PartialOrdering) {
- // C++0x [temp.deduct.partial]p5:
+ // C++11 [temp.deduct.partial]p5:
// Before the partial ordering is done, certain transformations are
// performed on the types used for partial ordering:
// - If P is a reference type, P is replaced by the type referred to.
@@ -1008,42 +972,42 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (ArgRef)
Arg = ArgRef->getPointeeType();
- if (RefParamComparisons && ParamRef && ArgRef) {
- // C++0x [temp.deduct.partial]p6:
- // If both P and A were reference types (before being replaced with the
- // type referred to above), determine which of the two types (if any) is
- // more cv-qualified than the other; otherwise the types are considered
- // to be equally cv-qualified for partial ordering purposes. The result
- // of this determination will be used below.
+ if (ParamRef && ArgRef && S.Context.hasSameUnqualifiedType(Param, Arg)) {
+ // C++11 [temp.deduct.partial]p9:
+ // If, for a given type, deduction succeeds in both directions (i.e.,
+ // the types are identical after the transformations above) and both
+ // P and A were reference types [...]:
+ // - if [one type] was an lvalue reference and [the other type] was
+ // not, [the other type] is not considered to be at least as
+ // specialized as [the first type]
+ // - if [one type] is more cv-qualified than [the other type],
+ // [the other type] is not considered to be at least as specialized
+ // as [the first type]
+ // Objective-C ARC adds:
+ // - [one type] has non-trivial lifetime, [the other type] has
+ // __unsafe_unretained lifetime, and the types are otherwise
+ // identical
//
- // We save this information for later, using it only when deduction
- // succeeds in both directions.
- RefParamPartialOrderingComparison Comparison;
- Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
- Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
- Comparison.Qualifiers = NeitherMoreQualified;
-
+ // A is "considered to be at least as specialized" as P iff deduction
+ // succeeds, so we model this as a deduction failure. Note that
+ // [the first type] is P and [the other type] is A here; the standard
+ // gets this backwards.
Qualifiers ParamQuals = Param.getQualifiers();
Qualifiers ArgQuals = Arg.getQualifiers();
- if (ParamQuals.isStrictSupersetOf(ArgQuals))
- Comparison.Qualifiers = ParamMoreQualified;
- else if (ArgQuals.isStrictSupersetOf(ParamQuals))
- Comparison.Qualifiers = ArgMoreQualified;
- else if (ArgQuals.getObjCLifetime() != ParamQuals.getObjCLifetime() &&
- ArgQuals.withoutObjCLifetime()
- == ParamQuals.withoutObjCLifetime()) {
- // Prefer binding to non-__unsafe_autoretained parameters.
- if (ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
- ParamQuals.getObjCLifetime())
- Comparison.Qualifiers = ParamMoreQualified;
- else if (ParamQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
- ArgQuals.getObjCLifetime())
- Comparison.Qualifiers = ArgMoreQualified;
+ if ((ParamRef->isLValueReferenceType() &&
+ !ArgRef->isLValueReferenceType()) ||
+ ParamQuals.isStrictSupersetOf(ArgQuals) ||
+ (ParamQuals.hasNonTrivialObjCLifetime() &&
+ ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
+ ParamQuals.withoutObjCLifetime() ==
+ ArgQuals.withoutObjCLifetime())) {
+ Info.FirstArg = TemplateArgument(ParamIn);
+ Info.SecondArg = TemplateArgument(ArgIn);
+ return Sema::TDK_NonDeducedMismatch;
}
- RefParamComparisons->push_back(Comparison);
}
- // C++0x [temp.deduct.partial]p7:
+ // C++11 [temp.deduct.partial]p7:
// Remove any top-level cv-qualifiers:
// - If P is a cv-qualified type, P is replaced by the cv-unqualified
// version of P.
@@ -2784,7 +2748,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
unsigned NumExplicitlySpecified,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) {
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
+ bool PartialOverloading) {
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
@@ -2911,6 +2876,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
Builder.size()));
+ if (PartialOverloading) break;
+
return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
}
@@ -3136,34 +3103,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
// are ignored for type deduction.
if (ParamType.hasQualifiers())
ParamType = ParamType.getUnqualifiedType();
- const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
- if (ParamRefType) {
- QualType PointeeType = ParamRefType->getPointeeType();
-
- // If the argument has incomplete array type, try to complete its type.
- if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
- ArgType = Arg->getType();
-
- // [C++0x] If P is an rvalue reference to a cv-unqualified
- // template parameter and the argument is an lvalue, the type
- // "lvalue reference to A" is used in place of A for type
- // deduction.
- if (isa<RValueReferenceType>(ParamType)) {
- if (!PointeeType.getQualifiers() &&
- isa<TemplateTypeParmType>(PointeeType) &&
- Arg->Classify(S.Context).isLValue() &&
- Arg->getType() != S.Context.OverloadTy &&
- Arg->getType() != S.Context.BoundMemberTy)
- ArgType = S.Context.getLValueReferenceType(ArgType);
- }
- // [...] If P is a reference type, the type referred to by P is used
- // for type deduction.
- ParamType = PointeeType;
- }
+ // [...] If P is a reference type, the type referred to by P is
+ // used for type deduction.
+ const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+ if (ParamRefType)
+ ParamType = ParamRefType->getPointeeType();
- // Overload sets usually make this parameter an undeduced
- // context, but there are sometimes special circumstances.
+ // Overload sets usually make this parameter an undeduced context,
+ // but there are sometimes special circumstances. Typically
+ // involving a template-id-expr.
if (ArgType == S.Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(S, TemplateParams,
Arg, ParamType,
@@ -3173,12 +3122,17 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
}
if (ParamRefType) {
+ // If the argument has incomplete array type, try to complete its type.
+ if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
+ ArgType = Arg->getType();
+
// C++0x [temp.deduct.call]p3:
- // [...] If P is of the form T&&, where T is a template parameter, and
- // the argument is an lvalue, the type A& is used in place of A for
- // type deduction.
+ // If P is an rvalue reference to a cv-unqualified template
+ // parameter and the argument is an lvalue, the type "lvalue
+ // reference to A" is used in place of A for type deduction.
if (ParamRefType->isRValueReferenceType() &&
- ParamRefType->getAs<TemplateTypeParmType>() &&
+ !ParamType.getQualifiers() &&
+ isa<TemplateTypeParmType>(ParamType) &&
Arg->isLValue())
ArgType = S.Context.getLValueReferenceType(ArgType);
} else {
@@ -3236,6 +3190,40 @@ static bool
hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate,
QualType T);
+static Sema::TemplateDeductionResult DeduceTemplateArgumentByListElement(
+ Sema &S, TemplateParameterList *TemplateParams, QualType ParamType,
+ Expr *Arg, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF);
+
+/// \brief Attempt template argument deduction from an initializer list
+/// deemed to be an argument in a function call.
+static bool
+DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
+ QualType AdjustedParamType, InitListExpr *ILE,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF, Sema::TemplateDeductionResult &Result) {
+ // If the argument is an initializer list then the parameter is an undeduced
+ // context, unless the parameter type is (reference to cv)
+ // std::initializer_list<P'>, in which case deduction is done for each element
+ // of the initializer list as-if it were an argument in a function call, and
+ // the result is the deduced type if it's the same for all elements.
+ QualType X;
+ if (!S.isStdInitializerList(AdjustedParamType, &X))
+ return false;
+
+ Result = Sema::TDK_Success;
+
+ // Recurse down into the init list.
+ for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+ if ((Result = DeduceTemplateArgumentByListElement(
+ S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF)))
+ return true;
+ }
+
+ return true;
+}
+
/// \brief Perform template argument deduction by matching a parameter type
/// against a single expression, where the expression is an element of
/// an initializer list that was originally matched against a parameter
@@ -3250,19 +3238,13 @@ DeduceTemplateArgumentByListElement(Sema &S,
// Handle the case where an init list contains another init list as the
// element.
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- QualType X;
- if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X))
+ Sema::TemplateDeductionResult Result;
+ if (!DeduceFromInitializerList(S, TemplateParams,
+ ParamType.getNonReferenceType(), ILE, Info,
+ Deduced, TDF, Result))
return Sema::TDK_Success; // Just ignore this expression.
- // Recurse down into the init list.
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (Sema::TemplateDeductionResult Result =
- DeduceTemplateArgumentByListElement(S, TemplateParams, X,
- ILE->getInit(i),
- Info, Deduced, TDF))
- return Result;
- }
- return Sema::TDK_Success;
+ return Result;
}
// For all other cases, just match by type.
@@ -3298,26 +3280,28 @@ DeduceTemplateArgumentByListElement(Sema &S,
Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
- FunctionDecl *&Specialization, TemplateDeductionInfo &Info) {
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
+ bool PartialOverloading) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ unsigned NumParams = Function->getNumParams();
// C++ [temp.deduct.call]p1:
// Template argument deduction is done by comparing each function template
// parameter type (call it P) with the type of the corresponding argument
// of the call (call it A) as described below.
unsigned CheckArgs = Args.size();
- if (Args.size() < Function->getMinRequiredArguments())
+ if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading)
return TDK_TooFewArguments;
- else if (Args.size() > Function->getNumParams()) {
+ else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) {
const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>();
if (Proto->isTemplateVariadic())
/* Do nothing */;
else if (Proto->isVariadic())
- CheckArgs = Function->getNumParams();
+ CheckArgs = NumParams;
else
return TDK_TooManyArguments;
}
@@ -3344,7 +3328,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
NumExplicitlySpecified = Deduced.size();
} else {
// Just fill in the parameter types from the function declaration.
- for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+ for (unsigned I = 0; I != NumParams; ++I)
ParamTypes.push_back(Function->getParamDecl(I)->getType());
}
@@ -3352,8 +3336,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
Deduced.resize(TemplateParams->size());
unsigned ArgIdx = 0;
SmallVector<OriginalCallArg, 4> OriginalCallArgs;
- for (unsigned ParamIdx = 0, NumParams = ParamTypes.size();
- ParamIdx != NumParams; ++ParamIdx) {
+ for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size();
+ ParamIdx != NumParamTypes; ++ParamIdx) {
QualType OrigParamType = ParamTypes[ParamIdx];
QualType ParamType = OrigParamType;
@@ -3379,22 +3363,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// If the argument is an initializer list ...
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- // ... then the parameter is an undeduced context, unless the parameter
- // type is (reference to cv) std::initializer_list<P'>, in which case
- // deduction is done for each element of the initializer list, and the
- // result is the deduced type if it's the same for all elements.
- QualType X;
+ TemplateDeductionResult Result;
// Removing references was already done.
- if (!isStdInitializerList(ParamType, &X))
+ if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
+ Info, Deduced, TDF, Result))
continue;
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (TemplateDeductionResult Result =
- DeduceTemplateArgumentByListElement(*this, TemplateParams, X,
- ILE->getInit(i),
- Info, Deduced, TDF))
- return Result;
- }
+ if (Result)
+ return Result;
// Don't track the argument type, since an initializer list has none.
continue;
}
@@ -3422,7 +3398,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// the function parameter pack. For a function parameter pack that does
// not occur at the end of the parameter-declaration-list, the type of
// the parameter pack is a non-deduced context.
- if (ParamIdx + 1 < NumParams)
+ if (ParamIdx + 1 < NumParamTypes)
break;
QualType ParamPattern = ParamExpansion->getPattern();
@@ -3450,19 +3426,15 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// As above, initializer lists need special handling.
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- QualType X;
- if (!isStdInitializerList(ParamType, &X)) {
+ TemplateDeductionResult Result;
+ if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
+ Info, Deduced, TDF, Result)) {
++ArgIdx;
break;
}
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (TemplateDeductionResult Result =
- DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
- ILE->getInit(i)->getType(),
- Info, Deduced, TDF))
- return Result;
- }
+ if (Result)
+ return Result;
} else {
// Keep track of the argument type and corresponding argument index,
@@ -3492,7 +3464,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
NumExplicitlySpecified, Specialization,
- Info, &OriginalCallArgs);
+ Info, &OriginalCallArgs,
+ PartialOverloading);
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
@@ -3699,8 +3672,10 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
FunctionTemplateDecl *InvokerTemplate = LambdaClass->
getLambdaStaticInvoker()->getDescribedFunctionTemplate();
- Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result
- = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
+#ifndef NDEBUG
+ Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
+#endif
+ S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
InvokerSpecialized, TDInfo);
assert(Result == Sema::TDK_Success &&
"If the call operator succeeded so should the invoker!");
@@ -3993,6 +3968,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
}
QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false);
+ if (Deduced.isNull())
+ return DAR_FailedAlreadyDiagnosed;
// FIXME: Support a non-canonical deduced type for 'auto'.
Deduced = Context.getCanonicalType(Deduced);
Result = SubstituteAutoTransform(*this, Deduced).Apply(Type);
@@ -4153,8 +4130,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments1,
- SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
+ unsigned NumCallArguments1) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
@@ -4219,8 +4195,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
Args2.resize(NumComparedArguments);
if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
Args1.data(), Args1.size(), Info, Deduced,
- TDF_None, /*PartialOrdering=*/true,
- RefParamComparisons))
+ TDF_None, /*PartialOrdering=*/true))
return false;
break;
@@ -4232,7 +4207,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
if (DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(),
Info, Deduced, TDF_None,
- /*PartialOrdering=*/true, RefParamComparisons))
+ /*PartialOrdering=*/true))
return false;
break;
@@ -4242,8 +4217,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
FD2->getType(), FD1->getType(),
Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- RefParamComparisons))
+ /*PartialOrdering=*/true))
return false;
break;
}
@@ -4342,83 +4316,17 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments1,
unsigned NumCallArguments2) {
- SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
- NumCallArguments1, nullptr);
+ NumCallArguments1);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
- NumCallArguments2,
- &RefParamComparisons);
+ NumCallArguments2);
if (Better1 != Better2) // We have a clear winner
- return Better1? FT1 : FT2;
+ return Better1 ? FT1 : FT2;
if (!Better1 && !Better2) // Neither is better than the other
return nullptr;
- // C++0x [temp.deduct.partial]p10:
- // If for each type being considered a given template is at least as
- // specialized for all types and more specialized for some set of types and
- // the other template is not more specialized for any types or is not at
- // least as specialized for any types, then the given template is more
- // specialized than the other template. Otherwise, neither template is more
- // specialized than the other.
- Better1 = false;
- Better2 = false;
- for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) {
- // C++0x [temp.deduct.partial]p9:
- // If, for a given type, deduction succeeds in both directions (i.e., the
- // types are identical after the transformations above) and both P and A
- // were reference types (before being replaced with the type referred to
- // above):
-
- // -- if the type from the argument template was an lvalue reference
- // and the type from the parameter template was not, the argument
- // type is considered to be more specialized than the other;
- // otherwise,
- if (!RefParamComparisons[I].ArgIsRvalueRef &&
- RefParamComparisons[I].ParamIsRvalueRef) {
- Better2 = true;
- if (Better1)
- return nullptr;
- continue;
- } else if (!RefParamComparisons[I].ParamIsRvalueRef &&
- RefParamComparisons[I].ArgIsRvalueRef) {
- Better1 = true;
- if (Better2)
- return nullptr;
- continue;
- }
-
- // -- if the type from the argument template is more cv-qualified than
- // the type from the parameter template (as described above), the
- // argument type is considered to be more specialized than the
- // other; otherwise,
- switch (RefParamComparisons[I].Qualifiers) {
- case NeitherMoreQualified:
- break;
-
- case ParamMoreQualified:
- Better1 = true;
- if (Better2)
- return nullptr;
- continue;
-
- case ArgMoreQualified:
- Better2 = true;
- if (Better1)
- return nullptr;
- continue;
- }
-
- // -- neither type is more specialized than the other.
- }
-
- assert(!(Better1 && Better2) && "Should have broken out in the loop above");
- if (Better1)
- return FT1;
- else if (Better2)
- return FT2;
-
// FIXME: This mimics what GCC implements, but doesn't match up with the
// proposed resolution for core issue 692. This area needs to be sorted out,
// but for now we attempt to maintain compatibility.
@@ -4591,8 +4499,7 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
PS2->getTemplateParameters(),
PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- /*RefParamComparisons=*/nullptr);
+ /*PartialOrdering=*/true);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
@@ -4605,8 +4512,7 @@ Sema::getMoreSpecializedPartialSpecialization(
Deduced.resize(PS1->getTemplateParameters()->size());
bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- /*RefParamComparisons=*/nullptr);
+ /*PartialOrdering=*/true);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
@@ -4649,8 +4555,7 @@ Sema::getMoreSpecializedPartialSpecialization(
Deduced.resize(PS2->getTemplateParameters()->size());
bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- /*RefParamComparisons=*/nullptr);
+ /*PartialOrdering=*/true);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
@@ -4666,8 +4571,7 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
PS1->getTemplateParameters(),
PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- /*RefParamComparisons=*/nullptr);
+ /*PartialOrdering=*/true);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6ac7175..c1961e5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -200,13 +200,19 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
llvm_unreachable("Invalid InstantiationKind!");
}
-void Sema::InstantiatingTemplate::Initialize(
- ActiveTemplateInstantiation::InstantiationKind Kind,
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind,
SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo *DeductionInfo) {
- SavedInNonInstantiationSFINAEContext =
- SemaRef.InNonInstantiationSFINAEContext;
+ sema::TemplateDeductionInfo *DeductionInfo)
+ : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext) {
+ // Don't allow further instantiation if a fatal error has occcured. Any
+ // diagnostics we might have raised will not be visible.
+ if (SemaRef.Diags.hasFatalErrorOccurred()) {
+ Invalid = true;
+ return;
+ }
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
@@ -225,124 +231,98 @@ void Sema::InstantiatingTemplate::Initialize(
}
}
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- Decl *Entity,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::TemplateInstantiation,
- PointOfInstantiation, InstantiationRange, Entity);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- FunctionDecl *Entity, ExceptionSpecification,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::ExceptionSpecInstantiation,
- PointOfInstantiation, InstantiationRange, Entity);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
- PointOfInstantiation, InstantiationRange,
- Template, nullptr, TemplateArgs);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- FunctionTemplateDecl *FunctionTemplate,
- ArrayRef<TemplateArgument> TemplateArgs,
- ActiveTemplateInstantiation::InstantiationKind Kind,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(Kind, PointOfInstantiation, InstantiationRange,
- FunctionTemplate, nullptr, TemplateArgs, &DeductionInfo);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ClassTemplatePartialSpecializationDecl *PartialSpec,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
- PointOfInstantiation, InstantiationRange,
- PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
-}
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(SemaRef,
+ ActiveTemplateInstantiation::TemplateInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity,
+ ExceptionSpecification, SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef, ActiveTemplateInstantiation::ExceptionSpecInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange, Template, nullptr,
+ TemplateArgs) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
+ InstantiationRange, FunctionTemplate, nullptr,
+ TemplateArgs, &DeductionInfo) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ClassTemplatePartialSpecializationDecl *PartialSpec,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
+ TemplateArgs, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
VarTemplatePartialSpecializationDecl *PartialSpec,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
- PointOfInstantiation, InstantiationRange,
- PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ParmVarDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation,
- PointOfInstantiation, InstantiationRange,
- Param, nullptr, TemplateArgs);
-}
-
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template, NonTypeTemplateParmDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
- PointOfInstantiation, InstantiationRange,
- Param, Template, TemplateArgs);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template, TemplateTemplateParmDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
- PointOfInstantiation, InstantiationRange,
- Param, Template, TemplateArgs);
-}
-
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template, NamedDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef)
-{
- Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentChecking,
- PointOfInstantiation, InstantiationRange,
- Param, Template, TemplateArgs);
-}
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
+ TemplateArgs, &DeductionInfo) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange, Param, nullptr,
+ TemplateArgs) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
+ NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange, Param, Template,
+ TemplateArgs) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
+ TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange, Param, Template,
+ TemplateArgs) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
+ NamedDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef, ActiveTemplateInstantiation::DefaultTemplateArgumentChecking,
+ PointOfInstantiation, InstantiationRange, Param, Template,
+ TemplateArgs) {}
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
@@ -734,6 +714,20 @@ namespace {
}
void transformedLocalDecl(Decl *Old, Decl *New) {
+ // If we've instantiated the call operator of a lambda or the call
+ // operator template of a generic lambda, update the "instantiation of"
+ // information.
+ auto *NewMD = dyn_cast<CXXMethodDecl>(New);
+ if (NewMD && isLambdaCallOperator(NewMD)) {
+ auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
+ if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
+ NewTD->setInstantiatedFromMemberTemplate(
+ OldMD->getDescribedFunctionTemplate());
+ else
+ NewMD->setInstantiationOfMemberFunction(OldMD,
+ TSK_ImplicitInstantiation);
+ }
+
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
}
@@ -836,28 +830,6 @@ namespace {
return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E);
}
- ExprResult TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *NewCallOperator,
- ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
- CXXMethodDecl *const OldCallOperator = E->getCallOperator();
- // In the generic lambda case, we set the NewTemplate to be considered
- // an "instantiation" of the OldTemplate.
- if (FunctionTemplateDecl *const NewCallOperatorTemplate =
- NewCallOperator->getDescribedFunctionTemplate()) {
-
- FunctionTemplateDecl *const OldCallOperatorTemplate =
- OldCallOperator->getDescribedFunctionTemplate();
- NewCallOperatorTemplate->setInstantiatedFromMemberTemplate(
- OldCallOperatorTemplate);
- } else
- // For a non-generic lambda we set the NewCallOperator to
- // be an instantiation of the OldCallOperator.
- NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator,
- TSK_ImplicitInstantiation);
-
- return inherited::TransformLambdaScope(E, NewCallOperator,
- InitCaptureExprsAndTypes);
- }
TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *OrigTPL) {
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
@@ -1017,7 +989,7 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
if (Id && Keyword != ETK_None && Keyword != ETK_Typename) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false,
- TagLocation, *Id)) {
+ TagLocation, Id)) {
SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
<< Id
<< FixItHint::CreateReplacement(SourceRange(TagLocation),
@@ -1708,11 +1680,24 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
} else if (OldParm->hasUnparsedDefaultArg()) {
NewParm->setUnparsedDefaultArg();
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
- } else if (Expr *Arg = OldParm->getDefaultArg())
- // FIXME: if we non-lazily instantiated non-dependent default args for
- // non-dependent parameter types we could remove a bunch of duplicate
- // conversion warnings for such arguments.
- NewParm->setUninstantiatedDefaultArg(Arg);
+ } else if (Expr *Arg = OldParm->getDefaultArg()) {
+ FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
+ CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
+ if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
+ // If this is a method of a local class, as per DR1484 its default
+ // arguments must be instantiated.
+ Sema::ContextRAII SavedContext(*this, ClassD);
+ LocalInstantiationScope Local(*this);
+ ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
+ if (NewArg.isUsable())
+ NewParm->setDefaultArg(NewArg.get());
+ } else {
+ // FIXME: if we non-lazily instantiated non-dependent default args for
+ // non-dependent parameter types we could remove a bunch of duplicate
+ // conversion warnings for such arguments.
+ NewParm->setUninstantiatedDefaultArg(Arg);
+ }
+ }
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
@@ -1767,7 +1752,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
- for (const auto Base : Pattern->bases()) {
+ for (const auto &Base : Pattern->bases()) {
if (!Base.getType()->isDependentType()) {
if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
if (RD->isInvalidDecl())
@@ -2063,6 +2048,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
SourceLocation(), SourceLocation(), nullptr);
CheckCompletedCXXClass(Instantiation);
+ // Default arguments are parsed, if not instantiated. We can go instantiate
+ // default arg exprs for default constructors if necessary now.
+ ActOnFinishCXXMemberDefaultArgs(Instantiation);
+
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
@@ -2257,7 +2246,7 @@ bool Sema::InstantiateInClassInitializer(
EnterExpressionEvaluationContext EvalContext(*this,
Sema::PotentiallyEvaluated);
- LocalInstantiationScope Scope(*this);
+ LocalInstantiationScope Scope(*this, true);
// Instantiate the initializer.
ActOnStartCXXInClassMemberInitializer();
@@ -2293,33 +2282,6 @@ bool Sema::InstantiateClassTemplateSpecialization(
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
-
- // Check whether we have already instantiated or specialized this class
- // template specialization.
- if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) {
- if (ClassTemplateSpec->getSpecializationKind() ==
- TSK_ExplicitInstantiationDeclaration &&
- TSK == TSK_ExplicitInstantiationDefinition) {
- // An explicit instantiation definition follows an explicit instantiation
- // declaration (C++0x [temp.explicit]p10); go ahead and perform the
- // explicit instantiation.
- ClassTemplateSpec->setSpecializationKind(TSK);
-
- // If this is an explicit instantiation definition, mark the
- // vtable as used.
- if (TSK == TSK_ExplicitInstantiationDefinition &&
- !ClassTemplateSpec->isInvalidDecl())
- MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
-
- return false;
- }
-
- // We can only instantiate something that hasn't already been
- // instantiated or specialized. Fail without any diagnostics: our
- // caller will provide an error message.
- return true;
- }
-
if (ClassTemplateSpec->isInvalidDecl())
return true;
@@ -2812,6 +2774,16 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
isa<TemplateTemplateParmDecl>(D))
return nullptr;
+ // Local types referenced prior to definition may require instantiation.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+ if (RD->isLocalClass())
+ return nullptr;
+
+ // Enumeration types referenced prior to definition may appear as a result of
+ // error recovery.
+ if (isa<EnumDecl>(D))
+ return nullptr;
+
// If we didn't find the decl, then we either have a sema bug, or we have a
// forward reference to a label declaration. Return null to indicate that
// we have an uninstantiated label.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 40e8617..aff2d1c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -202,6 +202,31 @@ static void instantiateDependentEnableIfAttr(
New->addAttr(EIA);
}
+// Constructs and adds to New a new instance of CUDALaunchBoundsAttr using
+// template A as the base and arguments from TemplateArgs.
+static void instantiateDependentCUDALaunchBoundsAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const CUDALaunchBoundsAttr &Attr, Decl *New) {
+ // The alignment expression is a constant expression.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
+
+ ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Expr *MaxThreads = Result.getAs<Expr>();
+
+ Expr *MinBlocks = nullptr;
+ if (Attr.getMinBlocks()) {
+ Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ MinBlocks = Result.getAs<Expr>();
+ }
+
+ S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks,
+ Attr.getSpellingListIndex());
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
@@ -233,6 +258,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ if (const CUDALaunchBoundsAttr *CUDALaunchBounds =
+ dyn_cast<CUDALaunchBoundsAttr>(TmplAttr)) {
+ instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs,
+ *CUDALaunchBounds, New);
+ continue;
+ }
+
// Existing DLL attribute on the instantiation takes precedence.
if (TmplAttr->getKind() == attr::DLLExport ||
TmplAttr->getKind() == attr::DLLImport) {
@@ -289,6 +321,11 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
}
Decl *
+TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) {
+ llvm_unreachable("extern \"C\" context cannot be instantiated");
+}
+
+Decl *
TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getIdentifier());
@@ -1265,11 +1302,19 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
// DR1484 clarifies that the members of a local class are instantiated as part
// of the instantiation of their enclosing entity.
if (D->isCompleteDefinition() && D->isLocalClass()) {
+ Sema::SavePendingLocalImplicitInstantiationsRAII
+ SavedPendingLocalImplicitInstantiations(SemaRef);
+
SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
TSK_ImplicitInstantiation,
/*Complain=*/true);
+
SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
TSK_ImplicitInstantiation);
+
+ // This class may have local implicit instantiations that need to be
+ // performed within this scope.
+ SemaRef.PerformPendingInstantiations(/*LocalOnly=*/true);
}
SemaRef.DiagnoseUnusedNestedTypedefs(Record);
@@ -1877,12 +1922,12 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
D->isParameterPack());
Inst->setAccess(AS_public);
- if (D->hasDefaultArgument()) {
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
TypeSourceInfo *InstantiatedDefaultArg =
SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs,
D->getDefaultArgumentLoc(), D->getDeclName());
if (InstantiatedDefaultArg)
- Inst->setDefaultArgument(InstantiatedDefaultArg, false);
+ Inst->setDefaultArgument(InstantiatedDefaultArg);
}
// Introduce this template parameter's instantiation into the instantiation
@@ -2033,10 +2078,10 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (Invalid)
Param->setInvalidDecl();
- if (D->hasDefaultArgument()) {
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs);
if (!Value.isInvalid())
- Param->setDefaultArgument(Value.get(), false);
+ Param->setDefaultArgument(Value.get());
}
// Introduce this template parameter's instantiation into the instantiation
@@ -2049,14 +2094,13 @@ static void collectUnexpandedParameterPacks(
Sema &S,
TemplateParameterList *Params,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- for (TemplateParameterList::const_iterator I = Params->begin(),
- E = Params->end(); I != E; ++I) {
- if ((*I)->isTemplateParameterPack())
+ for (const auto &P : *Params) {
+ if (P->isTemplateParameterPack())
continue;
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*I))
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
S.collectUnexpandedParameterPacks(NTTP->getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
- if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*I))
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
collectUnexpandedParameterPacks(S, TTP->getTemplateParameters(),
Unexpanded);
}
@@ -2160,7 +2204,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getPosition(),
D->isParameterPack(),
D->getIdentifier(), InstParams);
- if (D->hasDefaultArgument()) {
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
NestedNameSpecifierLoc QualifierLoc =
D->getDefaultArgument().getTemplateQualifierLoc();
QualifierLoc =
@@ -2170,10 +2214,10 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs);
if (!TName.isNull())
Param->setDefaultArgument(
+ SemaRef.Context,
TemplateArgumentLoc(TemplateArgument(TName),
D->getDefaultArgument().getTemplateQualifierLoc(),
- D->getDefaultArgument().getTemplateNameLoc()),
- false);
+ D->getDefaultArgument().getTemplateNameLoc()));
}
Param->setAccess(AS_public);
@@ -2686,9 +2730,8 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
typedef SmallVector<NamedDecl *, 8> ParamVector;
ParamVector Params;
Params.reserve(N);
- for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
- PI != PE; ++PI) {
- NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
+ for (auto &P : *L) {
+ NamedDecl *D = cast_or_null<NamedDecl>(Visit(P));
Params.push_back(D);
Invalid = Invalid || !D || D->isInvalidDecl();
}
@@ -3201,10 +3244,18 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// DR1330: In C++11, defer instantiation of a non-trivial
// exception specification.
+ // DR1484: Local classes and their members are instantiated along with the
+ // containing function.
+ bool RequireInstantiation = false;
+ if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
+ if (Cls->isLocalClass())
+ RequireInstantiation = true;
+ }
if (SemaRef.getLangOpts().CPlusPlus11 &&
EPI.ExceptionSpec.Type != EST_None &&
EPI.ExceptionSpec.Type != EST_DynamicNone &&
- EPI.ExceptionSpec.Type != EST_BasicNoexcept) {
+ EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
+ !RequireInstantiation) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
@@ -3313,12 +3364,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// it marks vtables used in late parsed templates as used.
SavePendingLocalImplicitInstantiationsRAII
SavedPendingLocalImplicitInstantiations(*this);
- std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
- SavePendingInstantiationsAndVTableUses;
- if (Recursive) {
- SavePendingInstantiationsAndVTableUses.reset(
- new SavePendingInstantiationsAndVTableUsesRAII(*this));
- }
+ SavePendingInstantiationsAndVTableUsesRAII
+ SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
// Call the LateTemplateParser callback if there is a need to late parse
// a templated function definition.
@@ -3463,8 +3510,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore PendingInstantiations and VTableUses.
- SavePendingInstantiationsAndVTableUses.reset();
+ // PendingInstantiations and VTableUses are restored through
+ // SavePendingInstantiationsAndVTableUses's destructor.
}
}
@@ -3780,12 +3827,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate
// later, while we're still within our own instantiation context.
- std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
- SavePendingInstantiationsAndVTableUses;
- if (Recursive) {
- SavePendingInstantiationsAndVTableUses.reset(
- new SavePendingInstantiationsAndVTableUsesRAII(*this));
- }
+ SavePendingInstantiationsAndVTableUsesRAII
+ SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
LocalInstantiationScope Local(*this);
@@ -3812,8 +3855,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore PendingInstantiations and VTableUses.
- SavePendingInstantiationsAndVTableUses.reset();
+ // PendingInstantiations and VTableUses are restored through
+ // SavePendingInstantiationsAndVTableUses's destructor.
}
}
@@ -3899,12 +3942,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// while we're still within our own instantiation context.
SavePendingLocalImplicitInstantiationsRAII
SavedPendingLocalImplicitInstantiations(*this);
- std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
- SavePendingInstantiationsAndVTableUses;
- if (Recursive) {
- SavePendingInstantiationsAndVTableUses.reset(
- new SavePendingInstantiationsAndVTableUsesRAII(*this));
- }
+ SavePendingInstantiationsAndVTableUsesRAII
+ SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
@@ -3970,8 +4009,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore PendingInstantiations and VTableUses.
- SavePendingInstantiationsAndVTableUses.reset();
+ // PendingInstantiations and VTableUses are restored through
+ // SavePendingInstantiationsAndVTableUses's destructor.
}
}
@@ -4409,6 +4448,30 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
if (D->isInvalidDecl())
return nullptr;
+ // Normally this function only searches for already instantiated declaration
+ // however we have to make an exclusion for local types used before
+ // definition as in the code:
+ //
+ // template<typename T> void f1() {
+ // void g1(struct x1);
+ // struct x1 {};
+ // }
+ //
+ // In this case instantiation of the type of 'g1' requires definition of
+ // 'x1', which is defined later. Error recovery may produce an enum used
+ // before definition. In these cases we need to instantiate relevant
+ // declarations here.
+ bool NeedInstantiate = false;
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+ NeedInstantiate = RD->isLocalClass();
+ else
+ NeedInstantiate = isa<EnumDecl>(D);
+ if (NeedInstantiate) {
+ Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
+ CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+ return cast<TypeDecl>(Inst);
+ }
+
// If we didn't find the decl, then we must have a label decl that hasn't
// been found yet. Lazily instantiate it and return it now.
assert(isa<LabelDecl>(D));
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index e4fab71..fd3ba35 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -251,15 +251,10 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
Locations.push_back(Unexpanded[I].second);
}
- DiagnosticBuilder DB
- = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0)
- << (int)UPPC
- : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1)
- << (int)UPPC << Names[0]
- : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2)
- << (int)UPPC << Names[0] << Names[1]
- : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
- << (int)UPPC << Names[0] << Names[1];
+ DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack)
+ << (int)UPPC << (int)Names.size();
+ for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I)
+ DB << Names[I];
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
DB << SourceRange(Locations[I]);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index 0f96a1c..02a31ef 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -22,8 +22,10 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -112,7 +114,6 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_SysVABI: \
case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs: \
- case AttributeList::AT_PnaclCall: \
case AttributeList::AT_IntelOclBicc
// Microsoft-specific type qualifiers.
@@ -122,6 +123,12 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_SPtr: \
case AttributeList::AT_UPtr
+// Nullability qualifiers.
+#define NULLABILITY_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_TypeNonNull: \
+ case AttributeList::AT_TypeNullable: \
+ case AttributeList::AT_TypeNullUnspecified
+
namespace {
/// An object which stores processing state for the entire
/// GetTypeForDeclarator process.
@@ -308,8 +315,12 @@ static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
///
/// \param i - a notional index which the search will start
/// immediately inside
+///
+/// \param onlyBlockPointers Whether we should only look into block
+/// pointer types (vs. all pointer types).
static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
- unsigned i) {
+ unsigned i,
+ bool onlyBlockPointers) {
assert(i <= declarator.getNumTypeObjects());
DeclaratorChunk *result = nullptr;
@@ -330,20 +341,26 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
return result;
// If we do find a function declarator, scan inwards from that,
- // looking for a block-pointer declarator.
+ // looking for a (block-)pointer declarator.
case DeclaratorChunk::Function:
for (--i; i != 0; --i) {
- DeclaratorChunk &blockChunk = declarator.getTypeObject(i-1);
- switch (blockChunk.Kind) {
+ DeclaratorChunk &ptrChunk = declarator.getTypeObject(i-1);
+ switch (ptrChunk.Kind) {
case DeclaratorChunk::Paren:
- case DeclaratorChunk::Pointer:
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
continue;
+
+ case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pointer:
+ if (onlyBlockPointers)
+ continue;
+
+ // fallthrough
+
case DeclaratorChunk::BlockPointer:
- result = &blockChunk;
+ result = &ptrChunk;
goto continue_outer;
}
llvm_unreachable("bad declarator chunk kind");
@@ -383,7 +400,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
attr.getKind() == AttributeList::AT_ObjCOwnership)
- destChunk = maybeMovePastReturnType(declarator, i - 1);
+ destChunk = maybeMovePastReturnType(declarator, i - 1,
+ /*onlyBlockPointers=*/true);
if (!destChunk) destChunk = &chunk;
moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
@@ -399,7 +417,9 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
case DeclaratorChunk::Function:
if (state.isProcessingDeclSpec() &&
attr.getKind() == AttributeList::AT_ObjCOwnership) {
- if (DeclaratorChunk *dest = maybeMovePastReturnType(declarator, i)) {
+ if (DeclaratorChunk *dest = maybeMovePastReturnType(
+ declarator, i,
+ /*onlyBlockPointers=*/true)) {
moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
dest->getAttrListRef());
return;
@@ -621,6 +641,13 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
// Microsoft type attributes cannot go after the declarator-id.
continue;
+ NULLABILITY_TYPE_ATTRS_CASELIST:
+ // Nullability specifiers cannot go after the declarator-id.
+
+ // Objective-C __kindof does not get distributed.
+ case AttributeList::AT_ObjCKindOf:
+ continue;
+
default:
break;
}
@@ -689,6 +716,444 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
state.setCurrentChunkIndex(declarator.getNumTypeObjects());
}
+static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
+ unsigned &TypeQuals,
+ QualType TypeSoFar,
+ unsigned RemoveTQs,
+ unsigned DiagID) {
+ // If this occurs outside a template instantiation, warn the user about
+ // it; they probably didn't mean to specify a redundant qualifier.
+ typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
+ for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
+ QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) {
+ if (!(RemoveTQs & Qual.first))
+ continue;
+
+ if (S.ActiveTemplateInstantiations.empty()) {
+ if (TypeQuals & Qual.first)
+ S.Diag(Qual.second, DiagID)
+ << DeclSpec::getSpecifierName(Qual.first) << TypeSoFar
+ << FixItHint::CreateRemoval(Qual.second);
+ }
+
+ TypeQuals &= ~Qual.first;
+ }
+}
+
+/// Apply Objective-C type arguments to the given type.
+static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
+ ArrayRef<TypeSourceInfo *> typeArgs,
+ SourceRange typeArgsRange,
+ bool failOnError = false) {
+ // We can only apply type arguments to an Objective-C class type.
+ const auto *objcObjectType = type->getAs<ObjCObjectType>();
+ if (!objcObjectType || !objcObjectType->getInterface()) {
+ S.Diag(loc, diag::err_objc_type_args_non_class)
+ << type
+ << typeArgsRange;
+
+ if (failOnError)
+ return QualType();
+ return type;
+ }
+
+ // The class type must be parameterized.
+ ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
+ ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
+ if (!typeParams) {
+ S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
+ << objcClass->getDeclName()
+ << FixItHint::CreateRemoval(typeArgsRange);
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // The type must not already be specialized.
+ if (objcObjectType->isSpecialized()) {
+ S.Diag(loc, diag::err_objc_type_args_specialized_class)
+ << type
+ << FixItHint::CreateRemoval(typeArgsRange);
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Check the type arguments.
+ SmallVector<QualType, 4> finalTypeArgs;
+ unsigned numTypeParams = typeParams->size();
+ bool anyPackExpansions = false;
+ for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
+ TypeSourceInfo *typeArgInfo = typeArgs[i];
+ QualType typeArg = typeArgInfo->getType();
+
+ // Type arguments cannot explicitly specify nullability.
+ if (auto nullability = AttributedType::stripOuterNullability(typeArg)) {
+ SourceLocation nullabilityLoc
+ = typeArgInfo->getTypeLoc().findNullabilityLoc();
+ SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc
+ : typeArgInfo->getTypeLoc().getLocStart();
+ S.Diag(diagLoc,
+ diag::err_type_arg_explicit_nullability)
+ << typeArg
+ << FixItHint::CreateRemoval(nullabilityLoc);
+ }
+
+ finalTypeArgs.push_back(typeArg);
+
+ if (typeArg->getAs<PackExpansionType>())
+ anyPackExpansions = true;
+
+ // Find the corresponding type parameter, if there is one.
+ ObjCTypeParamDecl *typeParam = nullptr;
+ if (!anyPackExpansions) {
+ if (i < numTypeParams) {
+ typeParam = typeParams->begin()[i];
+ } else {
+ // Too many arguments.
+ S.Diag(loc, diag::err_objc_type_args_wrong_arity)
+ << false
+ << objcClass->getDeclName()
+ << (unsigned)typeArgs.size()
+ << numTypeParams;
+ S.Diag(objcClass->getLocation(), diag::note_previous_decl)
+ << objcClass;
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+ }
+
+ // Objective-C object pointer types must be substitutable for the bounds.
+ if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
+ // If we don't have a type parameter to match against, assume
+ // everything is fine. There was a prior pack expansion that
+ // means we won't be able to match anything.
+ if (!typeParam) {
+ assert(anyPackExpansions && "Too many arguments?");
+ continue;
+ }
+
+ // Retrieve the bound.
+ QualType bound = typeParam->getUnderlyingType();
+ const auto *boundObjC = bound->getAs<ObjCObjectPointerType>();
+
+ // Determine whether the type argument is substitutable for the bound.
+ if (typeArgObjC->isObjCIdType()) {
+ // When the type argument is 'id', the only acceptable type
+ // parameter bound is 'id'.
+ if (boundObjC->isObjCIdType())
+ continue;
+ } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
+ // Otherwise, we follow the assignability rules.
+ continue;
+ }
+
+ // Diagnose the mismatch.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_arg_does_not_match_bound)
+ << typeArg << bound << typeParam->getDeclName();
+ S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
+ << typeParam->getDeclName();
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Block pointer types are permitted for unqualified 'id' bounds.
+ if (typeArg->isBlockPointerType()) {
+ // If we don't have a type parameter to match against, assume
+ // everything is fine. There was a prior pack expansion that
+ // means we won't be able to match anything.
+ if (!typeParam) {
+ assert(anyPackExpansions && "Too many arguments?");
+ continue;
+ }
+
+ // Retrieve the bound.
+ QualType bound = typeParam->getUnderlyingType();
+ if (bound->isBlockCompatibleObjCPointerType(S.Context))
+ continue;
+
+ // Diagnose the mismatch.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_arg_does_not_match_bound)
+ << typeArg << bound << typeParam->getDeclName();
+ S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
+ << typeParam->getDeclName();
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Dependent types will be checked at instantiation time.
+ if (typeArg->isDependentType()) {
+ continue;
+ }
+
+ // Diagnose non-id-compatible type arguments.
+ S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_arg_not_id_compatible)
+ << typeArg
+ << typeArgInfo->getTypeLoc().getSourceRange();
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Make sure we didn't have the wrong number of arguments.
+ if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {
+ S.Diag(loc, diag::err_objc_type_args_wrong_arity)
+ << (typeArgs.size() < typeParams->size())
+ << objcClass->getDeclName()
+ << (unsigned)finalTypeArgs.size()
+ << (unsigned)numTypeParams;
+ S.Diag(objcClass->getLocation(), diag::note_previous_decl)
+ << objcClass;
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+ }
+
+ // Success. Form the specialized type.
+ return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false);
+}
+
+/// Apply Objective-C protocol qualifiers to the given type.
+static QualType applyObjCProtocolQualifiers(
+ Sema &S, SourceLocation loc, SourceRange range, QualType type,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ const SourceLocation *protocolLocs,
+ bool failOnError = false) {
+ ASTContext &ctx = S.Context;
+ if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+
+ return ctx.getObjCObjectType(objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ }
+
+ if (type->isObjCObjectType()) {
+ // Silently overwrite any existing protocol qualifiers.
+ // TODO: determine whether that's the right thing to do.
+
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+ return ctx.getObjCObjectType(type, { }, protocols, false);
+ }
+
+ // id<protocol-list>
+ if (type->isObjCIdType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols,
+ objPtr->isKindOfType());
+ return ctx.getObjCObjectPointerType(type);
+ }
+
+ // Class<protocol-list>
+ if (type->isObjCClassType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = ctx.getObjCObjectType(ctx.ObjCBuiltinClassTy, { }, protocols,
+ objPtr->isKindOfType());
+ return ctx.getObjCObjectPointerType(type);
+ }
+
+ S.Diag(loc, diag::err_invalid_protocol_qualifiers)
+ << range;
+
+ if (failOnError)
+ return QualType();
+
+ return type;
+}
+
+QualType Sema::BuildObjCObjectType(QualType BaseType,
+ SourceLocation Loc,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc,
+ bool FailOnError) {
+ QualType Result = BaseType;
+ if (!TypeArgs.empty()) {
+ Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
+ SourceRange(TypeArgsLAngleLoc,
+ TypeArgsRAngleLoc),
+ FailOnError);
+ if (FailOnError && Result.isNull())
+ return QualType();
+ }
+
+ if (!Protocols.empty()) {
+ Result = applyObjCProtocolQualifiers(*this, Loc,
+ SourceRange(ProtocolLAngleLoc,
+ ProtocolRAngleLoc),
+ Result, Protocols,
+ ProtocolLocs.data(),
+ FailOnError);
+ if (FailOnError && Result.isNull())
+ return QualType();
+ }
+
+ return Result;
+}
+
+TypeResult Sema::actOnObjCProtocolQualifierType(
+ SourceLocation lAngleLoc,
+ ArrayRef<Decl *> protocols,
+ ArrayRef<SourceLocation> protocolLocs,
+ SourceLocation rAngleLoc) {
+ // Form id<protocol-list>.
+ QualType Result = Context.getObjCObjectType(
+ Context.ObjCBuiltinIdTy, { },
+ llvm::makeArrayRef(
+ (ObjCProtocolDecl * const *)protocols.data(),
+ protocols.size()),
+ false);
+ Result = Context.getObjCObjectPointerType(Result);
+
+ TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
+ TypeLoc ResultTL = ResultTInfo->getTypeLoc();
+
+ auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();
+ ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit
+
+ auto ObjCObjectTL = ObjCObjectPointerTL.getPointeeLoc()
+ .castAs<ObjCObjectTypeLoc>();
+ ObjCObjectTL.setHasBaseTypeAsWritten(false);
+ ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());
+
+ // No type arguments.
+ ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
+ ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
+
+ // Fill in protocol qualifiers.
+ ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);
+ ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);
+ for (unsigned i = 0, n = protocols.size(); i != n; ++i)
+ ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);
+
+ // We're done. Return the completed type to the parser.
+ return CreateParsedType(Result, ResultTInfo);
+}
+
+TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
+ Scope *S,
+ SourceLocation Loc,
+ ParsedType BaseType,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<ParsedType> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<Decl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc) {
+ TypeSourceInfo *BaseTypeInfo = nullptr;
+ QualType T = GetTypeFromParser(BaseType, &BaseTypeInfo);
+ if (T.isNull())
+ return true;
+
+ // Handle missing type-source info.
+ if (!BaseTypeInfo)
+ BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+
+ // Extract type arguments.
+ SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;
+ for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {
+ TypeSourceInfo *TypeArgInfo = nullptr;
+ QualType TypeArg = GetTypeFromParser(TypeArgs[i], &TypeArgInfo);
+ if (TypeArg.isNull()) {
+ ActualTypeArgInfos.clear();
+ break;
+ }
+
+ assert(TypeArgInfo && "No type source info?");
+ ActualTypeArgInfos.push_back(TypeArgInfo);
+ }
+
+ // Build the object type.
+ QualType Result = BuildObjCObjectType(
+ T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
+ TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
+ ProtocolLAngleLoc,
+ llvm::makeArrayRef((ObjCProtocolDecl * const *)Protocols.data(),
+ Protocols.size()),
+ ProtocolLocs, ProtocolRAngleLoc,
+ /*FailOnError=*/false);
+
+ if (Result == T)
+ return BaseType;
+
+ // Create source information for this type.
+ TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
+ TypeLoc ResultTL = ResultTInfo->getTypeLoc();
+
+ // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
+ // object pointer type. Fill in source information for it.
+ if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {
+ // The '*' is implicit.
+ ObjCObjectPointerTL.setStarLoc(SourceLocation());
+ ResultTL = ObjCObjectPointerTL.getPointeeLoc();
+ }
+
+ auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
+
+ // Type argument information.
+ if (ObjCObjectTL.getNumTypeArgs() > 0) {
+ assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());
+ ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);
+ ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);
+ for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)
+ ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);
+ } else {
+ ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
+ ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
+ }
+
+ // Protocol qualifier information.
+ if (ObjCObjectTL.getNumProtocols() > 0) {
+ assert(ObjCObjectTL.getNumProtocols() == Protocols.size());
+ ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
+ ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
+ for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
+ ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);
+ } else {
+ ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());
+ ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());
+ }
+
+ // Base type.
+ ObjCObjectTL.setHasBaseTypeAsWritten(true);
+ if (ObjCObjectTL.getType() == T)
+ ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());
+ else
+ ObjCObjectTL.getBaseLoc().initialize(Context, Loc);
+
+ // We're done. Return the completed type to the parser.
+ return CreateParsedType(Result, ResultTInfo);
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
@@ -752,15 +1217,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.Char32Ty;
break;
case DeclSpec::TST_unspecified:
- // "<proto1,proto2>" is an objc qualified ID with a missing id.
- if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
- Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl*const*)PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- break;
- }
-
// If this is a missing declspec in a block literal return context, then it
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
@@ -869,8 +1325,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
else
Result = Context.DoubleTy;
- if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64);
+ if (S.getLangOpts().OpenCL &&
+ !((S.getLangOpts().OpenCLVersion >= 120) ||
+ S.getOpenCLOptions().cl_khr_fp64)) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_fp64";
declarator.setInvalidType(true);
}
break;
@@ -915,36 +1374,31 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
Result = S.GetTypeFromParser(DS.getRepAsType());
- if (Result.isNull())
+ if (Result.isNull()) {
declarator.setInvalidType(true);
- else if (DeclSpec::ProtocolQualifierListTy PQ
- = DS.getProtocolQualifiers()) {
- if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
- // Silently drop any existing protocol qualifiers.
- // TODO: determine whether that's the right thing to do.
- if (ObjT->getNumProtocols())
- Result = ObjT->getBaseType();
-
- if (DS.getNumProtocolQualifiers())
- Result = Context.getObjCObjectType(Result,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- } else if (Result->isObjCIdType()) {
- // id<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else if (Result->isObjCClassType()) {
- // Class<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
- (ObjCProtocolDecl*const*) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else {
- S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
- << DS.getSourceRange();
- declarator.setInvalidType(true);
+ } else if (S.getLangOpts().OpenCL) {
+ if (const AtomicType *AT = Result->getAs<AtomicType>()) {
+ const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>();
+ bool NoExtTypes = BT && (BT->getKind() == BuiltinType::Int ||
+ BT->getKind() == BuiltinType::UInt ||
+ BT->getKind() == BuiltinType::Float);
+ if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_int64_base_atomics";
+ declarator.setInvalidType(true);
+ }
+ if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
+ !NoExtTypes) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_int64_extended_atomics";
+ declarator.setInvalidType(true);
+ }
+ if (!S.getOpenCLOptions().cl_khr_fp64 && BT &&
+ BT->getKind() == BuiltinType::Double) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_fp64";
+ declarator.setInvalidType(true);
+ }
}
}
@@ -1091,24 +1545,22 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
-
- // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
- // of a function type includes any type qualifiers, the behavior is
- // undefined."
- if (Result->isFunctionType() && TypeQuals) {
- if (TypeQuals & DeclSpec::TQ_const)
- S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
- else if (TypeQuals & DeclSpec::TQ_volatile)
- S.Diag(DS.getVolatileSpecLoc(),
- diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
- else {
- assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
- "Has CVRA quals but not C, V, R, or A?");
- // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a
- // function type later, in BuildQualifiedType.
- }
+ // Warn about CV qualifiers on function types.
+ // C99 6.7.3p8:
+ // If the specification of a function type includes any type qualifiers,
+ // the behavior is undefined.
+ // C++11 [dcl.fct]p7:
+ // The effect of a cv-qualifier-seq in a function declarator is not the
+ // same as adding cv-qualification on top of the function type. In the
+ // latter case, the cv-qualifiers are ignored.
+ if (TypeQuals && Result->isFunctionType()) {
+ diagnoseAndRemoveTypeQualifiers(
+ S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
+ S.getLangOpts().CPlusPlus
+ ? diag::warn_typecheck_function_qualifiers_ignored
+ : diag::warn_typecheck_function_qualifiers_unspecified);
+ // No diagnostic for 'restrict' or '_Atomic' applied to a
+ // function type; we'll diagnose those later, in BuildQualifiedType.
}
// C++11 [dcl.ref]p1:
@@ -1119,25 +1571,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// There don't appear to be any other contexts in which a cv-qualified
// reference type could be formed, so the 'ill-formed' clause here appears
// to never happen.
- if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
- TypeQuals && Result->isReferenceType()) {
- // If this occurs outside a template instantiation, warn the user about
- // it; they probably didn't mean to specify a redundant qualifier.
- typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
- QualLoc Quals[] = {
- QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
- QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
- QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
- };
- for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
- if (S.ActiveTemplateInstantiations.empty()) {
- if (TypeQuals & Quals[I].first)
- S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers)
- << DeclSpec::getSpecifierName(Quals[I].first) << Result
- << FixItHint::CreateRemoval(Quals[I].second);
- }
- TypeQuals &= ~Quals[I].first;
- }
+ if (TypeQuals && Result->isReferenceType()) {
+ diagnoseAndRemoveTypeQualifiers(
+ S, DS, TypeQuals, Result,
+ DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic,
+ diag::warn_typecheck_reference_qualifiers);
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
@@ -1809,13 +2247,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// exception specification.
if (CheckDistantExceptionSpec(T)) {
Diag(Loc, diag::err_distant_exception_spec);
-
- // FIXME: If we're doing this as part of template instantiation,
- // we should return immediately.
-
- // Build the type anyway, but use the canonical type so that the
- // exception specifiers are stripped off.
- T = Context.getCanonicalType(T);
+ return QualType();
}
// C++ 8.3.3p3: A pointer to member shall not point to ... a member
@@ -2463,6 +2895,10 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
+ } else if (D.getContext() == Declarator::LambdaExprContext) {
+ // This can only be a call operator for a lambda, which is an instance
+ // method.
+ IsCXXInstanceMethod = true;
} else {
// We're the innermost decl chunk, so must be a function declarator.
assert(D.isFunctionDeclarator());
@@ -2476,8 +2912,303 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
}
}
- return S.Context.getDefaultCallingConvention(FTI.isVariadic,
- IsCXXInstanceMethod);
+ CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
+ IsCXXInstanceMethod);
+
+ // Attribute AT_OpenCLKernel affects the calling convention only on
+ // the SPIR target, hence it cannot be treated as a calling
+ // convention attribute. This is the simplest place to infer
+ // "spir_kernel" for OpenCL kernels on SPIR.
+ if (CC == CC_SpirFunction) {
+ for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
+ CC = CC_SpirKernel;
+ break;
+ }
+ }
+ }
+
+ return CC;
+}
+
+namespace {
+ /// A simple notion of pointer kinds, which matches up with the various
+ /// pointer declarators.
+ enum class SimplePointerKind {
+ Pointer,
+ BlockPointer,
+ MemberPointer,
+ };
+}
+
+IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
+ switch (nullability) {
+ case NullabilityKind::NonNull:
+ if (!Ident__Nonnull)
+ Ident__Nonnull = PP.getIdentifierInfo("_Nonnull");
+ return Ident__Nonnull;
+
+ case NullabilityKind::Nullable:
+ if (!Ident__Nullable)
+ Ident__Nullable = PP.getIdentifierInfo("_Nullable");
+ return Ident__Nullable;
+
+ case NullabilityKind::Unspecified:
+ if (!Ident__Null_unspecified)
+ Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
+ return Ident__Null_unspecified;
+ }
+ llvm_unreachable("Unknown nullability kind.");
+}
+
+/// Retrieve the identifier "NSError".
+IdentifierInfo *Sema::getNSErrorIdent() {
+ if (!Ident_NSError)
+ Ident_NSError = PP.getIdentifierInfo("NSError");
+
+ return Ident_NSError;
+}
+
+/// Check whether there is a nullability attribute of any kind in the given
+/// attribute list.
+static bool hasNullabilityAttr(const AttributeList *attrs) {
+ for (const AttributeList *attr = attrs; attr;
+ attr = attr->getNext()) {
+ if (attr->getKind() == AttributeList::AT_TypeNonNull ||
+ attr->getKind() == AttributeList::AT_TypeNullable ||
+ attr->getKind() == AttributeList::AT_TypeNullUnspecified)
+ return true;
+ }
+
+ return false;
+}
+
+namespace {
+ /// Describes the kind of a pointer a declarator describes.
+ enum class PointerDeclaratorKind {
+ // Not a pointer.
+ NonPointer,
+ // Single-level pointer.
+ SingleLevelPointer,
+ // Multi-level pointer (of any pointer kind).
+ MultiLevelPointer,
+ // CFFooRef*
+ MaybePointerToCFRef,
+ // CFErrorRef*
+ CFErrorRefPointer,
+ // NSError**
+ NSErrorPointerPointer,
+ };
+}
+
+/// Classify the given declarator, whose type-specified is \c type, based on
+/// what kind of pointer it refers to.
+///
+/// This is used to determine the default nullability.
+static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
+ QualType type,
+ Declarator &declarator) {
+ unsigned numNormalPointers = 0;
+
+ // For any dependent type, we consider it a non-pointer.
+ if (type->isDependentType())
+ return PointerDeclaratorKind::NonPointer;
+
+ // Look through the declarator chunks to identify pointers.
+ for (unsigned i = 0, n = declarator.getNumTypeObjects(); i != n; ++i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ break;
+
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
+ : PointerDeclaratorKind::SingleLevelPointer;
+
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Reference:
+ continue;
+
+ case DeclaratorChunk::Pointer:
+ ++numNormalPointers;
+ if (numNormalPointers > 2)
+ return PointerDeclaratorKind::MultiLevelPointer;
+ continue;
+ }
+ }
+
+ // Then, dig into the type specifier itself.
+ unsigned numTypeSpecifierPointers = 0;
+ do {
+ // Decompose normal pointers.
+ if (auto ptrType = type->getAs<PointerType>()) {
+ ++numNormalPointers;
+
+ if (numNormalPointers > 2)
+ return PointerDeclaratorKind::MultiLevelPointer;
+
+ type = ptrType->getPointeeType();
+ ++numTypeSpecifierPointers;
+ continue;
+ }
+
+ // Decompose block pointers.
+ if (type->getAs<BlockPointerType>()) {
+ return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
+ : PointerDeclaratorKind::SingleLevelPointer;
+ }
+
+ // Decompose member pointers.
+ if (type->getAs<MemberPointerType>()) {
+ return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
+ : PointerDeclaratorKind::SingleLevelPointer;
+ }
+
+ // Look at Objective-C object pointers.
+ if (auto objcObjectPtr = type->getAs<ObjCObjectPointerType>()) {
+ ++numNormalPointers;
+ ++numTypeSpecifierPointers;
+
+ // If this is NSError**, report that.
+ if (auto objcClassDecl = objcObjectPtr->getInterfaceDecl()) {
+ if (objcClassDecl->getIdentifier() == S.getNSErrorIdent() &&
+ numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
+ return PointerDeclaratorKind::NSErrorPointerPointer;
+ }
+ }
+
+ break;
+ }
+
+ // Look at Objective-C class types.
+ if (auto objcClass = type->getAs<ObjCInterfaceType>()) {
+ if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) {
+ if (numNormalPointers == 2 && numTypeSpecifierPointers < 2)
+ return PointerDeclaratorKind::NSErrorPointerPointer;;
+ }
+
+ break;
+ }
+
+ // If at this point we haven't seen a pointer, we won't see one.
+ if (numNormalPointers == 0)
+ return PointerDeclaratorKind::NonPointer;
+
+ if (auto recordType = type->getAs<RecordType>()) {
+ RecordDecl *recordDecl = recordType->getDecl();
+
+ bool isCFError = false;
+ if (S.CFError) {
+ // If we already know about CFError, test it directly.
+ isCFError = (S.CFError == recordDecl);
+ } else {
+ // Check whether this is CFError, which we identify based on its bridge
+ // to NSError.
+ if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) {
+ if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>()) {
+ if (bridgeAttr->getBridgedType() == S.getNSErrorIdent()) {
+ S.CFError = recordDecl;
+ isCFError = true;
+ }
+ }
+ }
+ }
+
+ // If this is CFErrorRef*, report it as such.
+ if (isCFError && numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
+ return PointerDeclaratorKind::CFErrorRefPointer;
+ }
+ break;
+ }
+
+ break;
+ } while (true);
+
+
+ switch (numNormalPointers) {
+ case 0:
+ return PointerDeclaratorKind::NonPointer;
+
+ case 1:
+ return PointerDeclaratorKind::SingleLevelPointer;
+
+ case 2:
+ return PointerDeclaratorKind::MaybePointerToCFRef;
+
+ default:
+ return PointerDeclaratorKind::MultiLevelPointer;
+ }
+}
+
+static FileID getNullabilityCompletenessCheckFileID(Sema &S,
+ SourceLocation loc) {
+ // If we're anywhere in a function, method, or closure context, don't perform
+ // completeness checks.
+ for (DeclContext *ctx = S.CurContext; ctx; ctx = ctx->getParent()) {
+ if (ctx->isFunctionOrMethod())
+ return FileID();
+
+ if (ctx->isFileContext())
+ break;
+ }
+
+ // We only care about the expansion location.
+ loc = S.SourceMgr.getExpansionLoc(loc);
+ FileID file = S.SourceMgr.getFileID(loc);
+ if (file.isInvalid())
+ return FileID();
+
+ // Retrieve file information.
+ bool invalid = false;
+ const SrcMgr::SLocEntry &sloc = S.SourceMgr.getSLocEntry(file, &invalid);
+ if (invalid || !sloc.isFile())
+ return FileID();
+
+ // We don't want to perform completeness checks on the main file or in
+ // system headers.
+ const SrcMgr::FileInfo &fileInfo = sloc.getFile();
+ if (fileInfo.getIncludeLoc().isInvalid())
+ return FileID();
+ if (fileInfo.getFileCharacteristic() != SrcMgr::C_User &&
+ S.Diags.getSuppressSystemWarnings()) {
+ return FileID();
+ }
+
+ return file;
+}
+
+/// Check for consistent use of nullability.
+static void checkNullabilityConsistency(TypeProcessingState &state,
+ SimplePointerKind pointerKind,
+ SourceLocation pointerLoc) {
+ Sema &S = state.getSema();
+
+ // Determine which file we're performing consistency checking for.
+ FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
+ if (file.isInvalid())
+ return;
+
+ // If we haven't seen any type nullability in this file, we won't warn now
+ // about anything.
+ FileNullability &fileNullability = S.NullabilityMap[file];
+ if (!fileNullability.SawTypeNullability) {
+ // If this is the first pointer declarator in the file, record it.
+ if (fileNullability.PointerLoc.isInvalid() &&
+ !S.Context.getDiagnostics().isIgnored(diag::warn_nullability_missing,
+ pointerLoc)) {
+ fileNullability.PointerLoc = pointerLoc;
+ fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
+ }
+
+ return;
+ }
+
+ // Complain about missing nullability.
+ S.Diag(pointerLoc, diag::warn_nullability_missing)
+ << static_cast<unsigned>(pointerKind);
}
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
@@ -2547,6 +3278,249 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ // Determine whether we should infer _Nonnull on pointer types.
+ Optional<NullabilityKind> inferNullability;
+ bool inferNullabilityCS = false;
+ bool inferNullabilityInnerOnly = false;
+ bool inferNullabilityInnerOnlyComplete = false;
+
+ // Are we in an assume-nonnull region?
+ bool inAssumeNonNullRegion = false;
+ if (S.PP.getPragmaAssumeNonNullLoc().isValid() &&
+ !state.getDeclarator().isObjCWeakProperty() &&
+ !S.deduceWeakPropertyFromType(T)) {
+ inAssumeNonNullRegion = true;
+ // Determine which file we saw the assume-nonnull region in.
+ FileID file = getNullabilityCompletenessCheckFileID(
+ S, S.PP.getPragmaAssumeNonNullLoc());
+ if (!file.isInvalid()) {
+ FileNullability &fileNullability = S.NullabilityMap[file];
+
+ // If we haven't seen any type nullability before, now we have.
+ if (!fileNullability.SawTypeNullability) {
+ if (fileNullability.PointerLoc.isValid()) {
+ S.Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
+ << static_cast<unsigned>(fileNullability.PointerKind);
+ }
+
+ fileNullability.SawTypeNullability = true;
+ }
+ }
+ }
+
+ // Whether to complain about missing nullability specifiers or not.
+ enum {
+ /// Never complain.
+ CAMN_No,
+ /// Complain on the inner pointers (but not the outermost
+ /// pointer).
+ CAMN_InnerPointers,
+ /// Complain about any pointers that don't have nullability
+ /// specified or inferred.
+ CAMN_Yes
+ } complainAboutMissingNullability = CAMN_No;
+ unsigned NumPointersRemaining = 0;
+
+ if (IsTypedefName) {
+ // For typedefs, we do not infer any nullability (the default),
+ // and we only complain about missing nullability specifiers on
+ // inner pointers.
+ complainAboutMissingNullability = CAMN_InnerPointers;
+
+ if (T->canHaveNullability() && !T->getNullability(S.Context)) {
+ ++NumPointersRemaining;
+ }
+
+ for (unsigned i = 0, n = D.getNumTypeObjects(); i != n; ++i) {
+ DeclaratorChunk &chunk = D.getTypeObject(i);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ break;
+
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ ++NumPointersRemaining;
+ break;
+
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Reference:
+ continue;
+
+ case DeclaratorChunk::Pointer:
+ ++NumPointersRemaining;
+ continue;
+ }
+ }
+ } else {
+ bool isFunctionOrMethod = false;
+ switch (auto context = state.getDeclarator().getContext()) {
+ case Declarator::ObjCParameterContext:
+ case Declarator::ObjCResultContext:
+ case Declarator::PrototypeContext:
+ case Declarator::TrailingReturnContext:
+ isFunctionOrMethod = true;
+ // fallthrough
+
+ case Declarator::MemberContext:
+ if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
+ complainAboutMissingNullability = CAMN_No;
+ break;
+ }
+ // fallthrough
+
+ case Declarator::FileContext:
+ case Declarator::KNRTypeListContext:
+ complainAboutMissingNullability = CAMN_Yes;
+
+ // Nullability inference depends on the type and declarator.
+ switch (classifyPointerDeclarator(S, T, D)) {
+ case PointerDeclaratorKind::NonPointer:
+ case PointerDeclaratorKind::MultiLevelPointer:
+ // Cannot infer nullability.
+ break;
+
+ case PointerDeclaratorKind::SingleLevelPointer:
+ // Infer _Nonnull if we are in an assumes-nonnull region.
+ if (inAssumeNonNullRegion) {
+ inferNullability = NullabilityKind::NonNull;
+ inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
+ context == Declarator::ObjCResultContext);
+ }
+ break;
+
+ case PointerDeclaratorKind::CFErrorRefPointer:
+ case PointerDeclaratorKind::NSErrorPointerPointer:
+ // Within a function or method signature, infer _Nullable at both
+ // levels.
+ if (isFunctionOrMethod && inAssumeNonNullRegion)
+ inferNullability = NullabilityKind::Nullable;
+ break;
+
+ case PointerDeclaratorKind::MaybePointerToCFRef:
+ if (isFunctionOrMethod) {
+ // On pointer-to-pointer parameters marked cf_returns_retained or
+ // cf_returns_not_retained, if the outer pointer is explicit then
+ // infer the inner pointer as _Nullable.
+ auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
+ while (NextAttr) {
+ if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
+ NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained)
+ return true;
+ NextAttr = NextAttr->getNext();
+ }
+ return false;
+ };
+ if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
+ if (hasCFReturnsAttr(D.getAttributes()) ||
+ hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
+ hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) {
+ inferNullability = NullabilityKind::Nullable;
+ inferNullabilityInnerOnly = true;
+ }
+ }
+ }
+ break;
+ }
+ break;
+
+ case Declarator::ConversionIdContext:
+ complainAboutMissingNullability = CAMN_Yes;
+ break;
+
+ case Declarator::AliasDeclContext:
+ case Declarator::AliasTemplateContext:
+ case Declarator::BlockContext:
+ case Declarator::BlockLiteralContext:
+ case Declarator::ConditionContext:
+ case Declarator::CXXCatchContext:
+ case Declarator::CXXNewContext:
+ case Declarator::ForContext:
+ case Declarator::LambdaExprContext:
+ case Declarator::LambdaExprParameterContext:
+ case Declarator::ObjCCatchContext:
+ case Declarator::TemplateParamContext:
+ case Declarator::TemplateTypeArgContext:
+ case Declarator::TypeNameContext:
+ // Don't infer in these contexts.
+ break;
+ }
+ }
+
+ // Local function that checks the nullability for a given pointer declarator.
+ // Returns true if _Nonnull was inferred.
+ auto inferPointerNullability = [&](SimplePointerKind pointerKind,
+ SourceLocation pointerLoc,
+ AttributeList *&attrs) -> AttributeList * {
+ // We've seen a pointer.
+ if (NumPointersRemaining > 0)
+ --NumPointersRemaining;
+
+ // If a nullability attribute is present, there's nothing to do.
+ if (hasNullabilityAttr(attrs))
+ return nullptr;
+
+ // If we're supposed to infer nullability, do so now.
+ if (inferNullability && !inferNullabilityInnerOnlyComplete) {
+ AttributeList::Syntax syntax
+ = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
+ : AttributeList::AS_Keyword;
+ AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
+ .create(
+ S.getNullabilityKeyword(
+ *inferNullability),
+ SourceRange(pointerLoc),
+ nullptr, SourceLocation(),
+ nullptr, 0, syntax);
+
+ spliceAttrIntoList(*nullabilityAttr, attrs);
+
+ if (inferNullabilityCS) {
+ state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
+ ->setObjCDeclQualifier(ObjCDeclSpec::DQ_CSNullability);
+ }
+
+ if (inferNullabilityInnerOnly)
+ inferNullabilityInnerOnlyComplete = true;
+ return nullabilityAttr;
+ }
+
+ // If we're supposed to complain about missing nullability, do so
+ // now if it's truly missing.
+ switch (complainAboutMissingNullability) {
+ case CAMN_No:
+ break;
+
+ case CAMN_InnerPointers:
+ if (NumPointersRemaining == 0)
+ break;
+ // Fallthrough.
+
+ case CAMN_Yes:
+ checkNullabilityConsistency(state, pointerKind, pointerLoc);
+ }
+ return nullptr;
+ };
+
+ // If the type itself could have nullability but does not, infer pointer
+ // nullability and perform consistency checking.
+ if (T->canHaveNullability() && S.ActiveTemplateInstantiations.empty() &&
+ !T->getNullability(S.Context)) {
+ SimplePointerKind pointerKind = SimplePointerKind::Pointer;
+ if (T->isBlockPointerType())
+ pointerKind = SimplePointerKind::BlockPointer;
+ else if (T->isMemberPointerType())
+ pointerKind = SimplePointerKind::MemberPointer;
+
+ if (auto *attr = inferPointerNullability(
+ pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getMutableDeclSpec().getAttributes().getListRef())) {
+ T = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*inferNullability), T, T);
+ attr->setUsedAsTypeAttr();
+ }
+ }
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -2564,6 +3538,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (!LangOpts.Blocks)
S.Diag(DeclType.Loc, diag::err_blocks_disable);
+ // Handle pointer nullability.
+ inferPointerNullability(SimplePointerKind::BlockPointer,
+ DeclType.Loc, DeclType.getAttrListRef());
+
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
@@ -2576,6 +3554,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
// Build the type anyway.
}
+
+ // Handle pointer nullability
+ inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
+ DeclType.getAttrListRef());
+
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
if (DeclType.Ptr.TypeQuals)
@@ -2792,8 +3775,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// class type in C++.
if ((T.getCVRQualifiers() || T->isAtomicType()) &&
!(S.getLangOpts().CPlusPlus &&
- (T->isDependentType() || T->isRecordType())))
- diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
+ (T->isDependentType() || T->isRecordType()))) {
+ if (T->isVoidType() && !S.getLangOpts().CPlusPlus &&
+ D.getFunctionDefinitionKind() == FDK_Definition) {
+ // [6.9.1/3] qualified void return is invalid on a C
+ // function definition. Apparently ok on declarations and
+ // in C++ though (!)
+ S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T;
+ } else
+ diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
+ }
// Objective-C ARC ownership qualifiers are ignored on the function
// return type (by type canonicalization). Complain if this attribute
@@ -3009,6 +4000,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
+
+ // Handle pointer nullability.
+ inferPointerNullability(SimplePointerKind::MemberPointer,
+ DeclType.Loc, DeclType.getAttrListRef());
+
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
D.setInvalidType(true);
@@ -3424,8 +4420,6 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp:
return AttributeList::AT_Pcs;
- case AttributedType::attr_pnaclcall:
- return AttributeList::AT_PnaclCall;
case AttributedType::attr_inteloclbicc:
return AttributeList::AT_IntelOclBicc;
case AttributedType::attr_ms_abi:
@@ -3440,21 +4434,40 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_SPtr;
case AttributedType::attr_uptr:
return AttributeList::AT_UPtr;
+ case AttributedType::attr_nonnull:
+ return AttributeList::AT_TypeNonNull;
+ case AttributedType::attr_nullable:
+ return AttributeList::AT_TypeNullable;
+ case AttributedType::attr_null_unspecified:
+ return AttributeList::AT_TypeNullUnspecified;
+ case AttributedType::attr_objc_kindof:
+ return AttributeList::AT_ObjCKindOf;
}
llvm_unreachable("unexpected attribute kind!");
}
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const AttributeList *attrs) {
- AttributedType::Kind kind = TL.getAttrKind();
-
- assert(attrs && "no type attributes in the expected location!");
- AttributeList::Kind parsedKind = getAttrListKind(kind);
- while (attrs->getKind() != parsedKind) {
+ const AttributeList *attrs,
+ const AttributeList *DeclAttrs = nullptr) {
+ // DeclAttrs and attrs cannot be both empty.
+ assert((attrs || DeclAttrs) &&
+ "no type attributes in the expected location!");
+
+ AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind());
+ // Try to search for an attribute of matching kind in attrs list.
+ while (attrs && attrs->getKind() != parsedKind)
attrs = attrs->getNext();
- assert(attrs && "no matching attribute in expected location!");
+ if (!attrs) {
+ // No matching type attribute in attrs list found.
+ // Try searching through C++11 attributes in the declarator attribute list.
+ while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() ||
+ DeclAttrs->getKind() != parsedKind))
+ DeclAttrs = DeclAttrs->getNext();
+ attrs = DeclAttrs;
}
+ assert(attrs && "no matching type attribute in expected location!");
+
TL.setAttrNameLoc(attrs->getLoc());
if (TL.hasAttrExprOperand()) {
assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
@@ -3500,32 +4513,14 @@ namespace {
TL.setNameEndLoc(DS.getLocEnd());
}
void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
- // Handle the base type, which might not have been written explicitly.
- if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
- TL.setHasBaseTypeAsWritten(false);
- TL.getBaseLoc().initialize(Context, SourceLocation());
- } else {
- TL.setHasBaseTypeAsWritten(true);
- Visit(TL.getBaseLoc());
- }
-
- // Protocol qualifiers.
- if (DS.getProtocolQualifiers()) {
- assert(TL.getNumProtocols() > 0);
- assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
- TL.setLAngleLoc(DS.getProtocolLAngleLoc());
- TL.setRAngleLoc(DS.getSourceRange().getEnd());
- for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
- TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
- } else {
- assert(TL.getNumProtocols() == 0);
- TL.setLAngleLoc(SourceLocation());
- TL.setRAngleLoc(SourceLocation());
- }
+ TypeSourceInfo *RepTInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
+ TL.copy(RepTInfo->getTypeLoc());
}
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- TL.setStarLoc(SourceLocation());
- Visit(TL.getPointeeLoc());
+ TypeSourceInfo *RepTInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
+ TL.copy(RepTInfo->getTypeLoc());
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
TypeSourceInfo *TInfo = nullptr;
@@ -3808,6 +4803,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo) {
TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
+ const AttributeList *DeclAttrs = D.getAttributes();
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
@@ -3824,7 +4820,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
+ fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs);
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -4047,7 +5043,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// just be the return type of a block pointer.
if (state.isProcessingDeclSpec()) {
Declarator &D = state.getDeclarator();
- if (maybeMovePastReturnType(D, D.getNumTypeObjects()))
+ if (maybeMovePastReturnType(D, D.getNumTypeObjects(),
+ /*onlyBlockPointers=*/true))
return false;
}
}
@@ -4424,6 +5421,253 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
return false;
}
+bool Sema::checkNullabilityTypeSpecifier(QualType &type,
+ NullabilityKind nullability,
+ SourceLocation nullabilityLoc,
+ bool isContextSensitive) {
+ // We saw a nullability type specifier. If this is the first one for
+ // this file, note that.
+ FileID file = getNullabilityCompletenessCheckFileID(*this, nullabilityLoc);
+ if (!file.isInvalid()) {
+ FileNullability &fileNullability = NullabilityMap[file];
+ if (!fileNullability.SawTypeNullability) {
+ // If we have already seen a pointer declarator without a nullability
+ // annotation, complain about it.
+ if (fileNullability.PointerLoc.isValid()) {
+ Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
+ << static_cast<unsigned>(fileNullability.PointerKind);
+ }
+
+ fileNullability.SawTypeNullability = true;
+ }
+ }
+
+ // Check for existing nullability attributes on the type.
+ QualType desugared = type;
+ while (auto attributed = dyn_cast<AttributedType>(desugared.getTypePtr())) {
+ // Check whether there is already a null
+ if (auto existingNullability = attributed->getImmediateNullability()) {
+ // Duplicated nullability.
+ if (nullability == *existingNullability) {
+ Diag(nullabilityLoc, diag::warn_nullability_duplicate)
+ << DiagNullabilityKind(nullability, isContextSensitive)
+ << FixItHint::CreateRemoval(nullabilityLoc);
+
+ break;
+ }
+
+ // Conflicting nullability.
+ Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ << DiagNullabilityKind(nullability, isContextSensitive)
+ << DiagNullabilityKind(*existingNullability, false);
+ return true;
+ }
+
+ desugared = attributed->getModifiedType();
+ }
+
+ // If there is already a different nullability specifier, complain.
+ // This (unlike the code above) looks through typedefs that might
+ // have nullability specifiers on them, which means we cannot
+ // provide a useful Fix-It.
+ if (auto existingNullability = desugared->getNullability(Context)) {
+ if (nullability != *existingNullability) {
+ Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ << DiagNullabilityKind(nullability, isContextSensitive)
+ << DiagNullabilityKind(*existingNullability, false);
+
+ // Try to find the typedef with the existing nullability specifier.
+ if (auto typedefType = desugared->getAs<TypedefType>()) {
+ TypedefNameDecl *typedefDecl = typedefType->getDecl();
+ QualType underlyingType = typedefDecl->getUnderlyingType();
+ if (auto typedefNullability
+ = AttributedType::stripOuterNullability(underlyingType)) {
+ if (*typedefNullability == *existingNullability) {
+ Diag(typedefDecl->getLocation(), diag::note_nullability_here)
+ << DiagNullabilityKind(*existingNullability, false);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ // If this definitely isn't a pointer type, reject the specifier.
+ if (!desugared->canHaveNullability()) {
+ Diag(nullabilityLoc, diag::err_nullability_nonpointer)
+ << DiagNullabilityKind(nullability, isContextSensitive) << type;
+ return true;
+ }
+
+ // For the context-sensitive keywords/Objective-C property
+ // attributes, require that the type be a single-level pointer.
+ if (isContextSensitive) {
+ // Make sure that the pointee isn't itself a pointer type.
+ QualType pointeeType = desugared->getPointeeType();
+ if (pointeeType->isAnyPointerType() ||
+ pointeeType->isObjCObjectPointerType() ||
+ pointeeType->isMemberPointerType()) {
+ Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
+ << DiagNullabilityKind(nullability, true)
+ << type;
+ Diag(nullabilityLoc, diag::note_nullability_type_specifier)
+ << DiagNullabilityKind(nullability, false)
+ << type
+ << FixItHint::CreateReplacement(nullabilityLoc,
+ getNullabilitySpelling(nullability));
+ return true;
+ }
+ }
+
+ // Form the attributed type.
+ type = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(nullability), type, type);
+ return false;
+}
+
+bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
+ // Find out if it's an Objective-C object or object pointer type;
+ const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
+ const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
+ : type->getAs<ObjCObjectType>();
+
+ // If not, we can't apply __kindof.
+ if (!objType) {
+ // FIXME: Handle dependent types that aren't yet object types.
+ Diag(loc, diag::err_objc_kindof_nonobject)
+ << type;
+ return true;
+ }
+
+ // Rebuild the "equivalent" type, which pushes __kindof down into
+ // the object type.
+ QualType equivType = Context.getObjCObjectType(objType->getBaseType(),
+ objType->getTypeArgsAsWritten(),
+ objType->getProtocols(),
+ /*isKindOf=*/true);
+
+ // If we started with an object pointer type, rebuild it.
+ if (ptrType) {
+ equivType = Context.getObjCObjectPointerType(equivType);
+ if (auto nullability = type->getNullability(Context)) {
+ auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
+ equivType = Context.getAttributedType(attrKind, equivType, equivType);
+ }
+ }
+
+ // Build the attributed type to record where __kindof occurred.
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+ type,
+ equivType);
+
+ return false;
+}
+
+/// Map a nullability attribute kind to a nullability kind.
+static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
+ switch (kind) {
+ case AttributeList::AT_TypeNonNull:
+ return NullabilityKind::NonNull;
+
+ case AttributeList::AT_TypeNullable:
+ return NullabilityKind::Nullable;
+
+ case AttributeList::AT_TypeNullUnspecified:
+ return NullabilityKind::Unspecified;
+
+ default:
+ llvm_unreachable("not a nullability attribute kind");
+ }
+}
+
+/// Distribute a nullability type attribute that cannot be applied to
+/// the type specifier to a pointer, block pointer, or member pointer
+/// declarator, complaining if necessary.
+///
+/// \returns true if the nullability annotation was distributed, false
+/// otherwise.
+static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
+ QualType type,
+ AttributeList &attr) {
+ Declarator &declarator = state.getDeclarator();
+
+ /// Attempt to move the attribute to the specified chunk.
+ auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool {
+ // If there is already a nullability attribute there, don't add
+ // one.
+ if (hasNullabilityAttr(chunk.getAttrListRef()))
+ return false;
+
+ // Complain about the nullability qualifier being in the wrong
+ // place.
+ enum {
+ PK_Pointer,
+ PK_BlockPointer,
+ PK_MemberPointer,
+ PK_FunctionPointer,
+ PK_MemberFunctionPointer,
+ } pointerKind
+ = chunk.Kind == DeclaratorChunk::Pointer ? (inFunction ? PK_FunctionPointer
+ : PK_Pointer)
+ : chunk.Kind == DeclaratorChunk::BlockPointer ? PK_BlockPointer
+ : inFunction? PK_MemberFunctionPointer : PK_MemberPointer;
+
+ auto diag = state.getSema().Diag(attr.getLoc(),
+ diag::warn_nullability_declspec)
+ << DiagNullabilityKind(mapNullabilityAttrKind(attr.getKind()),
+ attr.isContextSensitiveKeywordAttribute())
+ << type
+ << static_cast<unsigned>(pointerKind);
+
+ // FIXME: MemberPointer chunks don't carry the location of the *.
+ if (chunk.Kind != DeclaratorChunk::MemberPointer) {
+ diag << FixItHint::CreateRemoval(attr.getLoc())
+ << FixItHint::CreateInsertion(
+ state.getSema().getPreprocessor()
+ .getLocForEndOfToken(chunk.Loc),
+ " " + attr.getName()->getName().str() + " ");
+ }
+
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ chunk.getAttrListRef());
+ return true;
+ };
+
+ // Move it to the outermost pointer, member pointer, or block
+ // pointer declarator.
+ for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ return moveToChunk(chunk, false);
+
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Array:
+ continue;
+
+ case DeclaratorChunk::Function:
+ // Try to move past the return type to a function/block/member
+ // function pointer.
+ if (DeclaratorChunk *dest = maybeMovePastReturnType(
+ declarator, i,
+ /*onlyBlockPointers=*/false)) {
+ return moveToChunk(*dest, true);
+ }
+
+ return false;
+
+ // Don't walk through these.
+ case DeclaratorChunk::Reference:
+ return false;
+ }
+ }
+
+ return false;
+}
+
static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
assert(!Attr.isInvalid());
switch (Attr.getKind()) {
@@ -4454,8 +5698,6 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
.Case("aapcs", AttributedType::attr_pcs)
.Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
}
- case AttributeList::AT_PnaclCall:
- return AttributedType::attr_pnaclcall;
case AttributeList::AT_IntelOclBicc:
return AttributedType::attr_inteloclbicc;
case AttributeList::AT_MSABI:
@@ -4932,6 +6174,47 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
+
+ NULLABILITY_TYPE_ATTRS_CASELIST:
+ // Either add nullability here or try to distribute it. We
+ // don't want to distribute the nullability specifier past any
+ // dependent type, because that complicates the user model.
+ if (type->canHaveNullability() || type->isDependentType() ||
+ !distributeNullabilityTypeAttr(state, type, attr)) {
+ if (state.getSema().checkNullabilityTypeSpecifier(
+ type,
+ mapNullabilityAttrKind(attr.getKind()),
+ attr.getLoc(),
+ attr.isContextSensitiveKeywordAttribute())) {
+ attr.setInvalid();
+ }
+
+ attr.setUsedAsTypeAttr();
+ }
+ break;
+
+ case AttributeList::AT_ObjCKindOf:
+ // '__kindof' must be part of the decl-specifiers.
+ switch (TAL) {
+ case TAL_DeclSpec:
+ break;
+
+ case TAL_DeclChunk:
+ case TAL_DeclName:
+ state.getSema().Diag(attr.getLoc(),
+ diag::err_objc_kindof_wrong_position)
+ << FixItHint::CreateRemoval(attr.getLoc())
+ << FixItHint::CreateInsertion(
+ state.getDeclarator().getDeclSpec().getLocStart(), "__kindof ");
+ break;
+ }
+
+ // Apply it regardless.
+ if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
+ attr.setInvalid();
+ attr.setUsedAsTypeAttr();
+ break;
+
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
@@ -5086,25 +6369,36 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
/// \param D The definition of the entity.
/// \param Suggested Filled in with the declaration that should be made visible
/// in order to provide a definition of this entity.
-static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
+/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
+/// not defined. This only matters for enums with a fixed underlying
+/// type, since in all other cases, a type is complete if and only if it
+/// is defined.
+bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+ bool OnlyNeedComplete) {
// Easy case: if we don't have modules, all declarations are visible.
- if (!S.getLangOpts().Modules)
+ if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
return true;
// If this definition was instantiated from a template, map back to the
// pattern from which it was instantiated.
- if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) {
+ // We're in the middle of defining it; this definition should be treated
+ // as visible.
+ return true;
+ } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (auto *Pattern = RD->getTemplateInstantiationPattern())
RD = Pattern;
D = RD->getDefinition();
} else if (auto *ED = dyn_cast<EnumDecl>(D)) {
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
ED = NewED;
- if (ED->isFixed()) {
- // If the enum has a fixed underlying type, any declaration of it will do.
+ if (OnlyNeedComplete && ED->isFixed()) {
+ // If the enum has a fixed underlying type, and we're only looking for a
+ // complete type (not a definition), any visible declaration of it will
+ // do.
*Suggested = nullptr;
for (auto *Redecl : ED->redecls()) {
- if (LookupResult::isVisible(S, Redecl))
+ if (isVisible(Redecl))
return true;
if (Redecl->isThisDeclarationADefinition() ||
(Redecl->isCanonicalDecl() && !*Suggested))
@@ -5116,10 +6410,18 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
}
assert(D && "missing definition for pattern of instantiated definition");
- // FIXME: If we merged any other decl into D, and that declaration is visible,
- // then we should consider a definition to be visible.
*Suggested = D;
- return LookupResult::isVisible(S, D);
+ if (isVisible(D))
+ return true;
+
+ // The external source may have additional definitions of this type that are
+ // visible, so complete the redeclaration chain now and ask again.
+ if (auto *Source = Context.getExternalSource()) {
+ Source->CompleteRedeclChain(D);
+ return isVisible(D);
+ }
+
+ return false;
}
/// Locks in the inheritance model for the given class and all of its bases.
@@ -5170,20 +6472,8 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
if (!Diagnoser.Suppressed && Def &&
- !hasVisibleDefinition(*this, Def, &SuggestedDef)) {
- // Suppress this error outside of a SFINAE context if we've already
- // emitted the error once for this type. There's no usefulness in
- // repeating the diagnostic.
- // FIXME: Add a Fix-It that imports the corresponding module or includes
- // the header.
- Module *Owner = SuggestedDef->getOwningModule();
- Diag(Loc, diag::err_module_private_definition)
- << T << Owner->getFullModuleName();
- Diag(SuggestedDef->getLocation(), diag::note_previous_definition);
-
- // Try to recover by implicitly importing this module.
- createImplicitModuleImportForErrorRecovery(Loc, Owner);
- }
+ !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true))
+ diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
// We lock in the inheritance model once somebody has asked us to ensure
// that a pointer-to-member type is complete.
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 36abbb6..6e193a3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -619,11 +619,6 @@ public:
StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
-
- typedef std::pair<ExprResult, QualType> InitCaptureInfoTy;
- /// \brief Transform the captures and body of a lambda expression.
- ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator,
- ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes);
TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *TPL) {
@@ -690,6 +685,27 @@ public:
QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
SourceLocation Sigil);
+ /// \brief Build an Objective-C object type.
+ ///
+ /// By default, performs semantic analysis when building the object type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildObjCObjectType(QualType BaseType,
+ SourceLocation Loc,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
+
+ /// \brief Build a new Objective-C object pointer type given the pointee type.
+ ///
+ /// By default, directly builds the pointer type, with no additional semantic
+ /// analysis.
+ QualType RebuildObjCObjectPointerType(QualType PointeeType,
+ SourceLocation Star);
+
/// \brief Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
/// qualifiers.
@@ -994,7 +1010,7 @@ public:
}
if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false,
- IdLoc, *Id)) {
+ IdLoc, Id)) {
SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;
SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);
return QualType();
@@ -1326,11 +1342,12 @@ public:
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildOMPExecutableDirective(OpenMPDirectiveKind Kind,
DeclarationNameInfo DirName,
+ OpenMPDirectiveKind CancelRegion,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPExecutableDirective(Kind, DirName, Clauses,
- AStmt, StartLoc, EndLoc);
+ return getSema().ActOnOpenMPExecutableDirective(
+ Kind, DirName, CancelRegion, Clauses, AStmt, StartLoc, EndLoc);
}
/// \brief Build a new OpenMP 'if' clause.
@@ -1556,6 +1573,19 @@ public:
EndLoc);
}
+ /// \brief Build a new OpenMP 'depend' pseudo clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *
+ RebuildOMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1702,7 +1732,7 @@ public:
}
StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, Stmt *Block) {
- return getSema().ActOnSEHFinallyBlock(Loc, Block);
+ return SEHFinallyStmt::Create(getSema().getASTContext(), Loc, Block);
}
/// \brief Build a new predefined expression.
@@ -1870,11 +1900,9 @@ public:
return ExprError();
Base = BaseResult.get();
ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
- MemberExpr *ME =
- new (getSema().Context) MemberExpr(Base, isArrow,
- Member, MemberNameInfo,
- cast<FieldDecl>(Member)->getType(),
- VK, OK_Ordinary);
+ MemberExpr *ME = new (getSema().Context)
+ MemberExpr(Base, isArrow, OpLoc, Member, MemberNameInfo,
+ cast<FieldDecl>(Member)->getType(), VK, OK_Ordinary);
return ME;
}
@@ -2625,6 +2653,31 @@ public:
RBracLoc, Args);
}
+ /// \brief Build a new Objective-C instance/class message to 'super'.
+ ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelectorLocs,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ MultiExprArg Args,
+ SourceLocation RBracLoc) {
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ QualType ReceiverTy = SemaRef.Context.getObjCInterfaceType(Class);
+
+ return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr,
+ ReceiverTy,
+ SuperLoc,
+ Sel, Method, LBracLoc, SelectorLocs,
+ RBracLoc, Args)
+ : SemaRef.BuildClassMessage(nullptr,
+ ReceiverTy,
+ SuperLoc,
+ Sel, Method, LBracLoc, SelectorLocs,
+ RBracLoc, Args);
+
+
+ }
+
/// \brief Build a new Objective-C ivar reference expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -5368,6 +5421,17 @@ QualType TreeTransform<Derived>::TransformAttributedType(
= getDerived().TransformType(oldType->getEquivalentType());
if (equivalentType.isNull())
return QualType();
+
+ // Check whether we can add nullability; it is only represented as
+ // type sugar, and therefore cannot be diagnosed in any other way.
+ if (auto nullability = oldType->getImmediateNullability()) {
+ if (!modifiedType->canHaveNullability()) {
+ SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
+ << DiagNullabilityKind(*nullability, false) << modifiedType;
+ return QualType();
+ }
+ }
+
result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
modifiedType,
equivalentType);
@@ -5563,18 +5627,153 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
ObjCObjectTypeLoc TL) {
- // ObjCObjectType is never dependent.
- TLB.pushFullCopy(TL);
- return TL.getType();
+ // Transform base type.
+ QualType BaseType = getDerived().TransformType(TLB, TL.getBaseLoc());
+ if (BaseType.isNull())
+ return QualType();
+
+ bool AnyChanged = BaseType != TL.getBaseLoc().getType();
+
+ // Transform type arguments.
+ SmallVector<TypeSourceInfo *, 4> NewTypeArgInfos;
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) {
+ TypeSourceInfo *TypeArgInfo = TL.getTypeArgTInfo(i);
+ TypeLoc TypeArgLoc = TypeArgInfo->getTypeLoc();
+ QualType TypeArg = TypeArgInfo->getType();
+ if (auto PackExpansionLoc = TypeArgLoc.getAs<PackExpansionTypeLoc>()) {
+ AnyChanged = true;
+
+ // We have a pack expansion. Instantiate it.
+ const auto *PackExpansion = PackExpansionLoc.getType()
+ ->castAs<PackExpansionType>();
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+ Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether the set of unexpanded parameter packs can
+ // and should be expanded.
+ TypeLoc PatternLoc = PackExpansionLoc.getPatternLoc();
+ bool Expand = false;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
+ if (getDerived().TryExpandParameterPacks(
+ PackExpansionLoc.getEllipsisLoc(), PatternLoc.getSourceRange(),
+ Unexpanded, Expand, RetainExpansion, NumExpansions))
+ return QualType();
+
+ if (!Expand) {
+ // We can't expand this pack expansion into separate arguments yet;
+ // just substitute into the pattern and create a new pack expansion
+ // type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+
+ TypeLocBuilder TypeArgBuilder;
+ TypeArgBuilder.reserve(PatternLoc.getFullDataSize());
+ QualType NewPatternType = getDerived().TransformType(TypeArgBuilder,
+ PatternLoc);
+ if (NewPatternType.isNull())
+ return QualType();
+
+ QualType NewExpansionType = SemaRef.Context.getPackExpansionType(
+ NewPatternType, NumExpansions);
+ auto NewExpansionLoc = TLB.push<PackExpansionTypeLoc>(NewExpansionType);
+ NewExpansionLoc.setEllipsisLoc(PackExpansionLoc.getEllipsisLoc());
+ NewTypeArgInfos.push_back(
+ TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewExpansionType));
+ continue;
+ }
+
+ // Substitute into the pack expansion pattern for each slice of the
+ // pack.
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), ArgIdx);
+
+ TypeLocBuilder TypeArgBuilder;
+ TypeArgBuilder.reserve(PatternLoc.getFullDataSize());
+
+ QualType NewTypeArg = getDerived().TransformType(TypeArgBuilder,
+ PatternLoc);
+ if (NewTypeArg.isNull())
+ return QualType();
+
+ NewTypeArgInfos.push_back(
+ TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewTypeArg));
+ }
+
+ continue;
+ }
+
+ TypeLocBuilder TypeArgBuilder;
+ TypeArgBuilder.reserve(TypeArgLoc.getFullDataSize());
+ QualType NewTypeArg = getDerived().TransformType(TypeArgBuilder, TypeArgLoc);
+ if (NewTypeArg.isNull())
+ return QualType();
+
+ // If nothing changed, just keep the old TypeSourceInfo.
+ if (NewTypeArg == TypeArg) {
+ NewTypeArgInfos.push_back(TypeArgInfo);
+ continue;
+ }
+
+ NewTypeArgInfos.push_back(
+ TypeArgBuilder.getTypeSourceInfo(SemaRef.Context, NewTypeArg));
+ AnyChanged = true;
+ }
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || AnyChanged) {
+ // Rebuild the type.
+ Result = getDerived().RebuildObjCObjectType(
+ BaseType,
+ TL.getLocStart(),
+ TL.getTypeArgsLAngleLoc(),
+ NewTypeArgInfos,
+ TL.getTypeArgsRAngleLoc(),
+ TL.getProtocolLAngleLoc(),
+ llvm::makeArrayRef(TL.getTypePtr()->qual_begin(),
+ TL.getNumProtocols()),
+ TL.getProtocolLocs(),
+ TL.getProtocolRAngleLoc());
+
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ObjCObjectTypeLoc NewT = TLB.push<ObjCObjectTypeLoc>(Result);
+ assert(TL.hasBaseTypeAsWritten() && "Can't be dependent");
+ NewT.setHasBaseTypeAsWritten(true);
+ NewT.setTypeArgsLAngleLoc(TL.getTypeArgsLAngleLoc());
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ NewT.setTypeArgTInfo(i, NewTypeArgInfos[i]);
+ NewT.setTypeArgsRAngleLoc(TL.getTypeArgsRAngleLoc());
+ NewT.setProtocolLAngleLoc(TL.getProtocolLAngleLoc());
+ for (unsigned i = 0, n = TL.getNumProtocols(); i != n; ++i)
+ NewT.setProtocolLoc(i, TL.getProtocolLoc(i));
+ NewT.setProtocolRAngleLoc(TL.getProtocolRAngleLoc());
+ return Result;
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
ObjCObjectPointerTypeLoc TL) {
- // ObjCObjectPointerType is never dependent.
- TLB.pushFullCopy(TL);
- return TL.getType();
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != TL.getPointeeLoc().getType()) {
+ Result = getDerived().RebuildObjCObjectPointerType(PointeeType,
+ TL.getStarLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result);
+ NewT.setStarLoc(TL.getStarLoc());
+ return Result;
}
//===----------------------------------------------------------------------===//
@@ -6635,7 +6834,9 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
I != E; ++I) {
if (*I) {
+ getDerived().getSema().StartOpenMPClause((*I)->getClauseKind());
OMPClause *Clause = getDerived().TransformOMPClause(*I);
+ getDerived().getSema().EndOpenMPClause();
if (Clause)
TClauses.push_back(Clause);
} else {
@@ -6647,7 +6848,16 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
if (!D->getAssociatedStmt()) {
return StmtError();
}
- AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt());
+ getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(),
+ /*CurScope=*/nullptr);
+ StmtResult Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(getSema());
+ Body = getDerived().TransformStmt(
+ cast<CapturedStmt>(D->getAssociatedStmt())->getCapturedStmt());
+ }
+ AssociatedStmt =
+ getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses);
if (AssociatedStmt.isInvalid()) {
return StmtError();
}
@@ -6662,10 +6872,16 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
DirName = cast<OMPCriticalDirective>(D)->getDirectiveName();
DirName = getDerived().TransformDeclarationNameInfo(DirName);
}
+ OpenMPDirectiveKind CancelRegion = OMPD_unknown;
+ if (D->getDirectiveKind() == OMPD_cancellation_point) {
+ CancelRegion = cast<OMPCancellationPointDirective>(D)->getCancelRegion();
+ } else if (D->getDirectiveKind() == OMPD_cancel) {
+ CancelRegion = cast<OMPCancelDirective>(D)->getCancelRegion();
+ }
return getDerived().RebuildOMPExecutableDirective(
- D->getDirectiveKind(), DirName, TClauses, AssociatedStmt.get(),
- D->getLocStart(), D->getLocEnd());
+ D->getDirectiveKind(), DirName, CancelRegion, TClauses,
+ AssociatedStmt.get(), D->getLocStart(), D->getLocEnd());
}
template <typename Derived>
@@ -6844,6 +7060,17 @@ TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
}
template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTaskgroupDirective(
+ OMPTaskgroupDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskgroup, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) {
DeclarationNameInfo DirName;
@@ -6898,6 +7125,28 @@ TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPCancellationPointDirective(
+ OMPCancellationPointDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_cancellation_point, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_cancel, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -7204,6 +7453,22 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPDependClause(
+ C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars,
+ C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -7834,6 +8099,9 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
+ if (InitListExpr *Syntactic = E->getSyntacticForm())
+ E = Syntactic;
+
bool InitChanged = false;
SmallVector<Expr*, 4> Inits;
@@ -7841,8 +8109,12 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
Inits, &InitChanged))
return ExprError();
- if (!getDerived().AlwaysRebuild() && !InitChanged)
- return E;
+ if (!getDerived().AlwaysRebuild() && !InitChanged) {
+ // FIXME: Attempt to reuse the existing syntactic form of the InitListExpr
+ // in some cases. We can't reuse it in general, because the syntactic and
+ // semantic forms are linked, and we can't know that semantic form will
+ // match even if the syntactic form does.
+ }
return getDerived().RebuildInitList(E->getLBraceLoc(), Inits,
E->getRBraceLoc(), E->getType());
@@ -7916,6 +8188,25 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
E->usesGNUSyntax(), Init.get());
}
+// Seems that if TransformInitListExpr() only works on the syntactic form of an
+// InitListExpr, then a DesignatedInitUpdateExpr is not encountered.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDesignatedInitUpdateExpr(
+ DesignatedInitUpdateExpr *E) {
+ llvm_unreachable("Unexpected DesignatedInitUpdateExpr in syntactic form of "
+ "initializer");
+ return ExprError();
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformNoInitExpr(
+ NoInitExpr *E) {
+ llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer");
+ return ExprError();
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformImplicitValueInitExpr(
@@ -9092,13 +9383,14 @@ ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// Transform any init-capture expressions before entering the scope of the
// lambda body, because they are not semantically within that scope.
+ typedef std::pair<ExprResult, QualType> InitCaptureInfoTy;
SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
- E->explicit_capture_begin());
+ E->explicit_capture_begin());
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
C != CEnd; ++C) {
- if (!C->isInitCapture())
+ if (!E->isInitCapture(C))
continue;
EnterExpressionEvaluationContext EEEC(getSema(),
Sema::PotentiallyEvaluated);
@@ -9120,12 +9412,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
std::make_pair(NewExprInitResult, NewInitCaptureType);
}
- LambdaScopeInfo *LSI = getSema().PushLambdaScope();
- Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
-
// Transform the template parameters, and add them to the current
// instantiation scope. The null case is handled correctly.
- LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
+ auto TPL = getDerived().TransformTemplateParameterList(
E->getTemplateParameterList());
// Transform the type of the original lambda's call operator.
@@ -9153,6 +9442,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
NewCallOpType);
}
+ LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+ Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
+ LSI->GLTemplateParameterList = TPL;
+
// Create the local class that will describe the lambda.
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
@@ -9169,34 +9462,22 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
LSI->CallOperator = NewCallOperator;
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
-
- // TransformLambdaScope will manage the function scope, so we can disable the
- // cleanup.
- FuncScopeCleanup.disable();
-
- return getDerived().TransformLambdaScope(E, NewCallOperator,
- InitCaptureExprsAndTypes);
-}
-
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *CallOperator,
- ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
- bool Invalid = false;
+ getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator);
// Introduce the context of the call operator.
- Sema::ContextRAII SavedContext(getSema(), CallOperator,
+ Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
/*NewThisContext*/false);
- LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
- getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
- E->getCaptureDefault(),
- E->getCaptureDefaultLoc(),
- E->hasExplicitParameters(),
- E->hasExplicitResultType(),
- E->isMutable());
+ getSema().buildLambdaScope(LSI, NewCallOperator,
+ E->getIntroducerRange(),
+ E->getCaptureDefault(),
+ E->getCaptureDefaultLoc(),
+ E->hasExplicitParameters(),
+ E->hasExplicitResultType(),
+ E->isMutable());
+
+ bool Invalid = false;
// Transform captures.
bool FinishedExplicitCaptures = false;
@@ -9221,8 +9502,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
continue;
// Rebuild init-captures, including the implied field declaration.
- if (C->isInitCapture()) {
-
+ if (E->isInitCapture(C)) {
InitCaptureInfoTy InitExprTypePair =
InitCaptureExprsAndTypes[C - E->capture_begin()];
ExprResult Init = InitExprTypePair.first;
@@ -9304,33 +9584,40 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
}
// Capture the transformed variable.
- getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
+ getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind,
+ EllipsisLoc);
}
if (!FinishedExplicitCaptures)
getSema().finishLambdaExplicitCaptures(LSI);
-
// Enter a new evaluation context to insulate the lambda from any
// cleanups from the enclosing full-expression.
getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
- if (Invalid) {
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
- /*IsInstantiation=*/true);
- return ExprError();
- }
-
// Instantiate the body of the lambda expression.
- StmtResult Body = getDerived().TransformStmt(E->getBody());
+ StmtResult Body =
+ Invalid ? StmtError() : getDerived().TransformStmt(E->getBody());
+
+ // ActOnLambda* will pop the function scope for us.
+ FuncScopeCleanup.disable();
+
if (Body.isInvalid()) {
+ SavedContext.pop();
getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
- return getSema().ActOnLambdaExpr(E->getLocStart(), Body.get(),
- /*CurScope=*/nullptr,
- /*IsInstantiation=*/true);
+ // Copy the LSI before ActOnFinishFunctionBody removes it.
+ // FIXME: This is dumb. Store the lambda information somewhere that outlives
+ // the call operator.
+ auto LSICopy = *LSI;
+ getSema().ActOnFinishFunctionBody(NewCallOperator, Body.get(),
+ /*IsInstantiation*/ true);
+ SavedContext.pop();
+
+ return getSema().BuildLambdaExpr(E->getLocStart(), Body.get()->getLocEnd(),
+ &LSICopy);
}
template<typename Derived>
@@ -10042,6 +10329,19 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
Args,
E->getRightLoc());
}
+ else if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
+ E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
+ // Build a new class message send to 'super'.
+ SmallVector<SourceLocation, 16> SelLocs;
+ E->getSelectorLocs(SelLocs);
+ return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(),
+ E->getSelector(),
+ SelLocs,
+ E->getMethodDecl(),
+ E->getLeftLoc(),
+ Args,
+ E->getRightLoc());
+ }
// Instance message: transform the receiver
assert(E->getReceiverKind() == ObjCMessageExpr::Instance &&
@@ -10350,6 +10650,31 @@ TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildObjCObjectType(
+ QualType BaseType,
+ SourceLocation Loc,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc) {
+ return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc,
+ TypeArgs, TypeArgsRAngleLoc,
+ ProtocolLAngleLoc, Protocols, ProtocolLocs,
+ ProtocolRAngleLoc,
+ /*FailOnError=*/true);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildObjCObjectPointerType(
+ QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.Context.getObjCObjectPointerType(PointeeType);
+}
+
+template<typename Derived>
QualType
TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
@@ -10720,11 +11045,9 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
!BaseType->getAs<PointerType>()->getPointeeType()
->template getAs<RecordType>())){
// This pseudo-destructor expression is still a pseudo-destructor.
- return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc,
- isArrow? tok::arrow : tok::period,
- SS, ScopeType, CCLoc, TildeLoc,
- Destroyed,
- /*FIXME?*/true);
+ return SemaRef.BuildPseudoDestructorExpr(
+ Base, OperatorLoc, isArrow ? tok::arrow : tok::period, SS, ScopeType,
+ CCLoc, TildeLoc, Destroyed);
}
TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
index 1339322..b1bf4a6 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -94,6 +94,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
switch (DC->getDeclKind()) {
// These entities may have multiple definitions.
case Decl::TranslationUnit:
+ case Decl::ExternCContext:
case Decl::Namespace:
case Decl::LinkageSpec:
return nullptr;
@@ -149,7 +150,11 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
bool serialization::isRedeclarableDeclKind(unsigned Kind) {
switch (static_cast<Decl::Kind>(Kind)) {
- case Decl::TranslationUnit: // Special case of a "merged" declaration.
+ case Decl::TranslationUnit:
+ case Decl::ExternCContext:
+ // Special case of a "merged" declaration.
+ return true;
+
case Decl::Namespace:
case Decl::NamespaceAlias:
case Decl::Typedef:
@@ -216,6 +221,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
// redeclarable.
case Decl::ImplicitParam:
case Decl::ParmVar:
+ case Decl::ObjCTypeParam:
return false;
}
@@ -223,6 +229,24 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
}
bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
+ // Friend declarations in dependent contexts aren't anonymous in the usual
+ // sense, but they cannot be found by name lookup in their semantic context
+ // (or indeed in any context), so we treat them as anonymous.
+ //
+ // This doesn't apply to friend tag decls; Sema makes those available to name
+ // lookup in the surrounding context.
+ if (D->getFriendObjectKind() &&
+ D->getLexicalDeclContext()->isDependentContext() && !isa<TagDecl>(D)) {
+ // For function templates and class templates, the template is numbered and
+ // not its pattern.
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ return !FD->getDescribedFunctionTemplate();
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+ return !RD->getDescribedClassTemplate();
+ return true;
+ }
+
+ // Otherwise, we only care about anonymous class members.
if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
return false;
return isa<TagDecl>(D) || isa<FieldDecl>(D);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
index 38a0ff5..f21e8a7 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/Serialization/ASTBitCodes.h"
namespace clang {
@@ -28,12 +29,15 @@ enum DeclUpdateKind {
UPD_CXX_ADDED_FUNCTION_DEFINITION,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
+ UPD_CXX_RESOLVED_DTOR_DELETE,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
UPD_DECL_MARKED_USED,
UPD_MANGLING_NUMBER,
UPD_STATIC_LOCAL_NUMBER,
- UPD_DECL_MARKED_OPENMP_THREADPRIVATE
+ UPD_DECL_MARKED_OPENMP_THREADPRIVATE,
+ UPD_DECL_EXPORTED,
+ UPD_ADDED_ATTR_TO_RECORD
};
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
@@ -85,6 +89,24 @@ bool isRedeclarableDeclKind(unsigned Kind);
/// declaration number.
bool needsAnonymousDeclarationNumber(const NamedDecl *D);
+/// \brief Visit each declaration within \c DC that needs an anonymous
+/// declaration number and call \p Visit with the declaration and its number.
+template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC,
+ Fn Visit) {
+ unsigned Index = 0;
+ for (Decl *LexicalD : DC->decls()) {
+ // For a friend decl, we care about the declaration within it, if any.
+ if (auto *FD = dyn_cast<FriendDecl>(LexicalD))
+ LexicalD = FD->getFriendDecl();
+
+ auto *ND = dyn_cast_or_null<NamedDecl>(LexicalD);
+ if (!ND || !needsAnonymousDeclarationNumber(ND))
+ continue;
+
+ Visit(ND, Index++);
+ }
+}
+
} // namespace serialization
} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 416164e..3045629 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===--- ASTReader.cpp - AST File Reader ----------------------------------===//
+//===-- ASTReader.cpp - AST File Reader ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
@@ -89,11 +90,13 @@ ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
Second->ReadLanguageOptions(LangOpts, Complain,
AllowCompatibleDifferences);
}
-bool
-ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) {
- return First->ReadTargetOptions(TargetOpts, Complain) ||
- Second->ReadTargetOptions(TargetOpts, Complain);
+bool ChainedASTReaderListener::ReadTargetOptions(
+ const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) {
+ return First->ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences) ||
+ Second->ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ChainedASTReaderListener::ReadDiagnosticOptions(
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
@@ -108,9 +111,12 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
}
bool ChainedASTReaderListener::ReadHeaderSearchOptions(
- const HeaderSearchOptions &HSOpts, bool Complain) {
- return First->ReadHeaderSearchOptions(HSOpts, Complain) ||
- Second->ReadHeaderSearchOptions(HSOpts, Complain);
+ const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath,
+ bool Complain) {
+ return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain) ||
+ Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain);
}
bool ChainedASTReaderListener::ReadPreprocessorOptions(
const PreprocessorOptions &PPOpts, bool Complain,
@@ -203,6 +209,12 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
+ if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) {
+ if (Diags)
+ Diags->Report(diag::err_pch_langopt_value_mismatch) << "module features";
+ return true;
+ }
+
if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
if (Diags)
Diags->Report(diag::err_pch_langopt_value_mismatch)
@@ -229,7 +241,8 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
/// \returns true if the target options mis-match, false otherwise.
static bool checkTargetOptions(const TargetOptions &TargetOpts,
const TargetOptions &ExistingTargetOpts,
- DiagnosticsEngine *Diags) {
+ DiagnosticsEngine *Diags,
+ bool AllowCompatibleDifferences = true) {
#define CHECK_TARGET_OPT(Field, Name) \
if (TargetOpts.Field != ExistingTargetOpts.Field) { \
if (Diags) \
@@ -238,9 +251,16 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
return true; \
}
+ // The triple and ABI must match exactly.
CHECK_TARGET_OPT(Triple, "target");
- CHECK_TARGET_OPT(CPU, "target CPU");
CHECK_TARGET_OPT(ABI, "target ABI");
+
+ // We can tolerate different CPUs in many cases, notably when one CPU
+ // supports a strict superset of another. When allowing compatible
+ // differences skip this check.
+ if (!AllowCompatibleDifferences)
+ CHECK_TARGET_OPT(CPU, "target CPU");
+
#undef CHECK_TARGET_OPT
// Compare feature sets.
@@ -252,43 +272,31 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
std::sort(ReadFeatures.begin(), ReadFeatures.end());
- unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
- unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
- while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
- if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
- ++ExistingIdx;
- ++ReadIdx;
- continue;
- }
-
- if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
- if (Diags)
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << false << ReadFeatures[ReadIdx];
- return true;
- }
-
- if (Diags)
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << true << ExistingFeatures[ExistingIdx];
- return true;
- }
+ // We compute the set difference in both directions explicitly so that we can
+ // diagnose the differences differently.
+ SmallVector<StringRef, 4> UnmatchedExistingFeatures, UnmatchedReadFeatures;
+ std::set_difference(
+ ExistingFeatures.begin(), ExistingFeatures.end(), ReadFeatures.begin(),
+ ReadFeatures.end(), std::back_inserter(UnmatchedExistingFeatures));
+ std::set_difference(ReadFeatures.begin(), ReadFeatures.end(),
+ ExistingFeatures.begin(), ExistingFeatures.end(),
+ std::back_inserter(UnmatchedReadFeatures));
+
+ // If we are allowing compatible differences and the read feature set is
+ // a strict subset of the existing feature set, there is nothing to diagnose.
+ if (AllowCompatibleDifferences && UnmatchedReadFeatures.empty())
+ return false;
- if (ExistingIdx < ExistingN) {
- if (Diags)
+ if (Diags) {
+ for (StringRef Feature : UnmatchedReadFeatures)
Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << true << ExistingFeatures[ExistingIdx];
- return true;
- }
-
- if (ReadIdx < ReadN) {
- if (Diags)
+ << /* is-existing-feature */ false << Feature;
+ for (StringRef Feature : UnmatchedExistingFeatures)
Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << false << ReadFeatures[ReadIdx];
- return true;
+ << /* is-existing-feature */ true << Feature;
}
- return false;
+ return !UnmatchedReadFeatures.empty() || !UnmatchedExistingFeatures.empty();
}
bool
@@ -302,10 +310,12 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
}
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) {
+ bool Complain,
+ bool AllowCompatibleDifferences) {
const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
return checkTargetOptions(TargetOpts, ExistingTargetOpts,
- Complain? &Reader.Diags : nullptr);
+ Complain ? &Reader.Diags : nullptr,
+ AllowCompatibleDifferences);
}
namespace {
@@ -464,7 +474,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
Macros[MacroName] = std::make_pair(MacroBody, false);
}
}
-
+
/// \brief Check the preprocessor options deserialized from the control block
/// against the preprocessor options in an existing preprocessor.
///
@@ -591,6 +601,36 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
PP.getLangOpts());
}
+/// Check the header search options deserialized from the control block
+/// against the header search options in an existing preprocessor.
+///
+/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ StringRef ExistingModuleCachePath,
+ DiagnosticsEngine *Diags,
+ const LangOptions &LangOpts) {
+ if (LangOpts.Modules) {
+ if (SpecificModuleCachePath != ExistingModuleCachePath) {
+ if (Diags)
+ Diags->Report(diag::err_pch_modulecache_mismatch)
+ << SpecificModuleCachePath << ExistingModuleCachePath;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) {
+ return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ PP.getHeaderSearchInfo().getModuleCachePath(),
+ Complain ? &Reader.Diags : nullptr,
+ PP.getLangOpts());
+}
+
void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
PP.setCounterValue(Value);
}
@@ -744,8 +784,6 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
Bits >>= 1;
bool ExtensionToken = Bits & 0x01;
Bits >>= 1;
- bool hasSubmoduleMacros = Bits & 0x01;
- Bits >>= 1;
bool hadMacroDefinition = Bits & 0x01;
Bits >>= 1;
@@ -787,49 +825,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
uint32_t MacroDirectivesOffset =
endian::readNext<uint32_t, little, unaligned>(d);
DataLen -= 4;
- SmallVector<uint32_t, 8> LocalMacroIDs;
- if (hasSubmoduleMacros) {
- while (true) {
- uint32_t LocalMacroID =
- endian::readNext<uint32_t, little, unaligned>(d);
- DataLen -= 4;
- if (LocalMacroID == 0xdeadbeef) break;
- LocalMacroIDs.push_back(LocalMacroID);
- }
- }
-
- if (F.Kind == MK_ImplicitModule || F.Kind == MK_ExplicitModule) {
- // Macro definitions are stored from newest to oldest, so reverse them
- // before registering them.
- llvm::SmallVector<unsigned, 8> MacroSizes;
- for (SmallVectorImpl<uint32_t>::iterator
- I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) {
- unsigned Size = 1;
-
- static const uint32_t HasOverridesFlag = 0x80000000U;
- if (I + 1 != E && (I[1] & HasOverridesFlag))
- Size += 1 + (I[1] & ~HasOverridesFlag);
- MacroSizes.push_back(Size);
- I += Size;
- }
-
- SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end();
- for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(),
- SE = MacroSizes.rend();
- SI != SE; ++SI) {
- I -= *SI;
-
- uint32_t LocalMacroID = *I;
- ArrayRef<uint32_t> Overrides;
- if (*SI != 1)
- Overrides = llvm::makeArrayRef(&I[2], *SI - 2);
- Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides);
- }
- assert(I == LocalMacroIDs.begin());
- } else {
- Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset);
- }
+ Reader.addPendingMacro(II, &F, MacroDirectivesOffset);
}
Reader.SetIdentifierInfo(ID, II);
@@ -848,7 +845,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
}
unsigned
-ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
+ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) {
llvm::FoldingSetNodeID ID;
ID.AddInteger(Key.Kind);
@@ -877,7 +874,7 @@ ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
ASTDeclContextNameLookupTrait::internal_key_type
ASTDeclContextNameLookupTrait::GetInternalKey(
- const external_key_type& Name) const {
+ const external_key_type& Name) {
DeclNameKey Key;
Key.Kind = Name.getNameKind();
switch (Name.getNameKind()) {
@@ -1393,6 +1390,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
PreprocessorRecordTypes RecType =
(PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record);
switch (RecType) {
+ case PP_MODULE_MACRO:
case PP_MACRO_DIRECTIVE_HISTORY:
return Macro;
@@ -1441,10 +1439,10 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
PreprocessedEntityID
GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);
PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
- PreprocessingRecord::PPEntityID
- PPID = PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true);
- MacroDefinition *PPDef =
- cast_or_null<MacroDefinition>(PPRec.getPreprocessedEntity(PPID));
+ PreprocessingRecord::PPEntityID PPID =
+ PPRec.getPPEntityID(GlobalID - 1, /*isLoaded=*/true);
+ MacroDefinitionRecord *PPDef = cast_or_null<MacroDefinitionRecord>(
+ PPRec.getPreprocessedEntity(PPID));
if (PPDef)
PPRec.RegisterMacroDefinition(Macro, PPDef);
}
@@ -1586,24 +1584,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
return HFI;
}
-void
-ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M,
- GlobalMacroID GMacID,
- ArrayRef<SubmoduleID> Overrides) {
- assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
- SubmoduleID *OverrideData = nullptr;
- if (!Overrides.empty()) {
- OverrideData = new (Context) SubmoduleID[Overrides.size() + 1];
- OverrideData[0] = Overrides.size();
- for (unsigned I = 0; I != Overrides.size(); ++I)
- OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]);
- }
- PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData));
-}
-
-void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II,
- ModuleFile *M,
- uint64_t MacroDirectivesOffset) {
+void ASTReader::addPendingMacro(IdentifierInfo *II,
+ ModuleFile *M,
+ uint64_t MacroDirectivesOffset) {
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset));
}
@@ -1661,6 +1644,7 @@ namespace {
/// \brief Visitor class used to look up identifirs in an AST file.
class IdentifierLookupVisitor {
StringRef Name;
+ unsigned NameHash;
unsigned PriorGeneration;
unsigned &NumIdentifierLookups;
unsigned &NumIdentifierLookupHits;
@@ -1670,7 +1654,8 @@ namespace {
IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration,
unsigned &NumIdentifierLookups,
unsigned &NumIdentifierLookupHits)
- : Name(Name), PriorGeneration(PriorGeneration),
+ : Name(Name), NameHash(ASTIdentifierLookupTrait::ComputeHash(Name)),
+ PriorGeneration(PriorGeneration),
NumIdentifierLookups(NumIdentifierLookups),
NumIdentifierLookupHits(NumIdentifierLookupHits),
Found()
@@ -1693,7 +1678,8 @@ namespace {
ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
M, This->Found);
++This->NumIdentifierLookups;
- ASTIdentifierLookupTable::iterator Pos = IdTable->find(This->Name,&Trait);
+ ASTIdentifierLookupTable::iterator Pos =
+ IdTable->find_hashed(This->Name, This->NameHash, &Trait);
if (Pos == IdTable->end())
return false;
@@ -1747,110 +1733,81 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
IdentifierGeneration[II] = getGeneration();
}
-struct ASTReader::ModuleMacroInfo {
- SubmoduleID SubModID;
- MacroInfo *MI;
- SubmoduleID *Overrides;
- // FIXME: Remove this.
- ModuleFile *F;
-
- bool isDefine() const { return MI; }
-
- SubmoduleID getSubmoduleID() const { return SubModID; }
-
- ArrayRef<SubmoduleID> getOverriddenSubmodules() const {
- if (!Overrides)
- return None;
- return llvm::makeArrayRef(Overrides + 1, *Overrides);
- }
-
- MacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
- if (!MI)
- return PP.AllocateUndefMacroDirective(ImportLoc, SubModID,
- getOverriddenSubmodules());
- return PP.AllocateDefMacroDirective(MI, ImportLoc, SubModID,
- getOverriddenSubmodules());
- }
-};
-
-ASTReader::ModuleMacroInfo *
-ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) {
- ModuleMacroInfo Info;
-
- uint32_t ID = PMInfo.ModuleMacroData.MacID;
- if (ID & 1) {
- // Macro undefinition.
- Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1);
- Info.MI = nullptr;
- } else {
- // Macro definition.
- GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1);
- assert(GMacID);
-
- // If this macro has already been loaded, don't do so again.
- // FIXME: This is highly dubious. Multiple macro definitions can have the
- // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc.
- if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
- return nullptr;
+void ASTReader::resolvePendingMacro(IdentifierInfo *II,
+ const PendingMacroInfo &PMInfo) {
+ ModuleFile &M = *PMInfo.M;
- Info.MI = getMacro(GMacID);
- Info.SubModID = Info.MI->getOwningModuleID();
- }
- Info.Overrides = PMInfo.ModuleMacroData.Overrides;
- Info.F = PMInfo.M;
+ BitstreamCursor &Cursor = M.MacroCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(PMInfo.MacroDirectivesOffset);
- return new (Context) ModuleMacroInfo(Info);
-}
+ struct ModuleMacroRecord {
+ SubmoduleID SubModID;
+ MacroInfo *MI;
+ SmallVector<SubmoduleID, 8> Overrides;
+ };
+ llvm::SmallVector<ModuleMacroRecord, 8> ModuleMacros;
-void ASTReader::resolvePendingMacro(IdentifierInfo *II,
- const PendingMacroInfo &PMInfo) {
- assert(II);
+ // We expect to see a sequence of PP_MODULE_MACRO records listing exported
+ // macros, followed by a PP_MACRO_DIRECTIVE_HISTORY record with the complete
+ // macro histroy.
+ RecordData Record;
+ while (true) {
+ llvm::BitstreamEntry Entry =
+ Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (Entry.Kind != llvm::BitstreamEntry::Record) {
+ Error("malformed block record in AST file");
+ return;
+ }
- if (PMInfo.M->Kind != MK_ImplicitModule &&
- PMInfo.M->Kind != MK_ExplicitModule) {
- installPCHMacroDirectives(II, *PMInfo.M,
- PMInfo.PCHMacroData.MacroDirectivesOffset);
- return;
- }
+ Record.clear();
+ switch ((PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record)) {
+ case PP_MACRO_DIRECTIVE_HISTORY:
+ break;
- // Module Macro.
+ case PP_MODULE_MACRO: {
+ ModuleMacros.push_back(ModuleMacroRecord());
+ auto &Info = ModuleMacros.back();
+ Info.SubModID = getGlobalSubmoduleID(M, Record[0]);
+ Info.MI = getMacro(getGlobalMacroID(M, Record[1]));
+ for (int I = 2, N = Record.size(); I != N; ++I)
+ Info.Overrides.push_back(getGlobalSubmoduleID(M, Record[I]));
+ continue;
+ }
- ModuleMacroInfo *MMI = getModuleMacro(PMInfo);
- if (!MMI)
- return;
+ default:
+ Error("malformed block record in AST file");
+ return;
+ }
- Module *Owner = getSubmodule(MMI->getSubmoduleID());
- if (Owner && Owner->NameVisibility == Module::Hidden) {
- // Macros in the owning module are hidden. Just remember this macro to
- // install if we make this module visible.
- HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI));
- } else {
- installImportedMacro(II, MMI, Owner);
+ // We found the macro directive history; that's the last record
+ // for this macro.
+ break;
}
-}
-
-void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
- ModuleFile &M, uint64_t Offset) {
- assert(M.Kind != MK_ImplicitModule && M.Kind != MK_ExplicitModule);
- BitstreamCursor &Cursor = M.MacroCursor;
- SavedStreamPosition SavedPosition(Cursor);
- Cursor.JumpToBit(Offset);
+ // Module macros are listed in reverse dependency order.
+ {
+ std::reverse(ModuleMacros.begin(), ModuleMacros.end());
+ llvm::SmallVector<ModuleMacro*, 8> Overrides;
+ for (auto &MMR : ModuleMacros) {
+ Overrides.clear();
+ for (unsigned ModID : MMR.Overrides) {
+ Module *Mod = getSubmodule(ModID);
+ auto *Macro = PP.getModuleMacro(Mod, II);
+ assert(Macro && "missing definition for overridden macro");
+ Overrides.push_back(Macro);
+ }
- llvm::BitstreamEntry Entry =
- Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
- if (Entry.Kind != llvm::BitstreamEntry::Record) {
- Error("malformed block record in AST file");
- return;
+ bool Inserted = false;
+ Module *Owner = getSubmodule(MMR.SubModID);
+ PP.addModuleMacro(Owner, II, MMR.MI, Overrides, Inserted);
+ }
}
- RecordData Record;
- PreprocessorRecordTypes RecType =
- (PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record);
- if (RecType != PP_MACRO_DIRECTIVE_HISTORY) {
- Error("malformed block record in AST file");
+ // Don't read the directive history for a module; we don't have anywhere
+ // to put it.
+ if (M.Kind == MK_ImplicitModule || M.Kind == MK_ExplicitModule)
return;
- }
// Deserialize the macro directives history in reverse source-order.
MacroDirective *Latest = nullptr, *Earliest = nullptr;
@@ -1861,31 +1818,12 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++];
switch (K) {
case MacroDirective::MD_Define: {
- GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
- MacroInfo *MI = getMacro(GMacID);
- SubmoduleID ImportedFrom = Record[Idx++];
- bool IsAmbiguous = Record[Idx++];
- llvm::SmallVector<unsigned, 4> Overrides;
- if (ImportedFrom) {
- Overrides.insert(Overrides.end(),
- &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]);
- Idx += Overrides.size() + 1;
- }
- DefMacroDirective *DefMD =
- PP.AllocateDefMacroDirective(MI, Loc, ImportedFrom, Overrides);
- DefMD->setAmbiguous(IsAmbiguous);
- MD = DefMD;
+ MacroInfo *MI = getMacro(getGlobalMacroID(M, Record[Idx++]));
+ MD = PP.AllocateDefMacroDirective(MI, Loc);
break;
}
case MacroDirective::MD_Undefine: {
- SubmoduleID ImportedFrom = Record[Idx++];
- llvm::SmallVector<unsigned, 4> Overrides;
- if (ImportedFrom) {
- Overrides.insert(Overrides.end(),
- &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]);
- Idx += Overrides.size() + 1;
- }
- MD = PP.AllocateUndefMacroDirective(Loc, ImportedFrom, Overrides);
+ MD = PP.AllocateUndefMacroDirective(Loc);
break;
}
case MacroDirective::MD_Visibility:
@@ -1901,177 +1839,8 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
Earliest = MD;
}
- PP.setLoadedMacroDirective(II, Latest);
-}
-
-/// \brief For the given macro definitions, check if they are both in system
-/// modules.
-static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI,
- Module *NewOwner, ASTReader &Reader) {
- assert(PrevMI && NewMI);
- Module *PrevOwner = nullptr;
- if (SubmoduleID PrevModID = PrevMI->getOwningModuleID())
- PrevOwner = Reader.getSubmodule(PrevModID);
- SourceManager &SrcMgr = Reader.getSourceManager();
- bool PrevInSystem
- = PrevOwner? PrevOwner->IsSystem
- : SrcMgr.isInSystemHeader(PrevMI->getDefinitionLoc());
- bool NewInSystem
- = NewOwner? NewOwner->IsSystem
- : SrcMgr.isInSystemHeader(NewMI->getDefinitionLoc());
- if (PrevOwner && PrevOwner == NewOwner)
- return false;
- return PrevInSystem && NewInSystem;
-}
-
-void ASTReader::removeOverriddenMacros(IdentifierInfo *II,
- SourceLocation ImportLoc,
- AmbiguousMacros &Ambig,
- ArrayRef<SubmoduleID> Overrides) {
- for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) {
- SubmoduleID OwnerID = Overrides[OI];
-
- // If this macro is not yet visible, remove it from the hidden names list.
- // It won't be there if we're in the middle of making the owner visible.
- Module *Owner = getSubmodule(OwnerID);
- auto HiddenIt = HiddenNamesMap.find(Owner);
- if (HiddenIt != HiddenNamesMap.end()) {
- HiddenNames &Hidden = HiddenIt->second;
- HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II);
- if (HI != Hidden.HiddenMacros.end()) {
- // Register the macro now so we don't lose it when we re-export.
- PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc));
-
- auto SubOverrides = HI->second->getOverriddenSubmodules();
- Hidden.HiddenMacros.erase(HI);
- removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides);
- }
- }
-
- // If this macro is already in our list of conflicts, remove it from there.
- Ambig.erase(
- std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) {
- return MD->getInfo()->getOwningModuleID() == OwnerID;
- }),
- Ambig.end());
- }
-}
-
-ASTReader::AmbiguousMacros *
-ASTReader::removeOverriddenMacros(IdentifierInfo *II,
- SourceLocation ImportLoc,
- ArrayRef<SubmoduleID> Overrides) {
- MacroDirective *Prev = PP.getMacroDirective(II);
- if (!Prev && Overrides.empty())
- return nullptr;
-
- DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective()
- : nullptr;
- if (PrevDef && PrevDef->isAmbiguous()) {
- // We had a prior ambiguity. Check whether we resolve it (or make it worse).
- AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
- Ambig.push_back(PrevDef);
-
- removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
-
- if (!Ambig.empty())
- return &Ambig;
-
- AmbiguousMacroDefs.erase(II);
- } else {
- // There's no ambiguity yet. Maybe we're introducing one.
- AmbiguousMacros Ambig;
- if (PrevDef)
- Ambig.push_back(PrevDef);
-
- removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
-
- if (!Ambig.empty()) {
- AmbiguousMacros &Result = AmbiguousMacroDefs[II];
- std::swap(Result, Ambig);
- return &Result;
- }
- }
-
- // We ended up with no ambiguity.
- return nullptr;
-}
-
-void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
- Module *Owner) {
- assert(II && Owner);
-
- SourceLocation ImportLoc = Owner->MacroVisibilityLoc;
- if (ImportLoc.isInvalid()) {
- // FIXME: If we made macros from this module visible but didn't provide a
- // source location for the import, we don't have a location for the macro.
- // Use the location at which the containing module file was first imported
- // for now.
- ImportLoc = MMI->F->DirectImportLoc;
- assert(ImportLoc.isValid() && "no import location for a visible macro?");
- }
-
- AmbiguousMacros *Prev =
- removeOverriddenMacros(II, ImportLoc, MMI->getOverriddenSubmodules());
-
- // Create a synthetic macro definition corresponding to the import (or null
- // if this was an undefinition of the macro).
- MacroDirective *Imported = MMI->import(PP, ImportLoc);
- DefMacroDirective *MD = dyn_cast<DefMacroDirective>(Imported);
-
- // If there's no ambiguity, just install the macro.
- if (!Prev) {
- PP.appendMacroDirective(II, Imported);
- return;
- }
- assert(!Prev->empty());
-
- if (!MD) {
- // We imported a #undef that didn't remove all prior definitions. The most
- // recent prior definition remains, and we install it in the place of the
- // imported directive, as if by a local #pragma pop_macro.
- MacroInfo *NewMI = Prev->back()->getInfo();
- Prev->pop_back();
- MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc);
-
- // Install our #undef first so that we don't lose track of it. We'll replace
- // this with whichever macro definition ends up winning.
- PP.appendMacroDirective(II, Imported);
- }
-
- // We're introducing a macro definition that creates or adds to an ambiguity.
- // We can resolve that ambiguity if this macro is token-for-token identical to
- // all of the existing definitions.
- MacroInfo *NewMI = MD->getInfo();
- assert(NewMI && "macro definition with no MacroInfo?");
- while (!Prev->empty()) {
- MacroInfo *PrevMI = Prev->back()->getInfo();
- assert(PrevMI && "macro definition with no MacroInfo?");
-
- // Before marking the macros as ambiguous, check if this is a case where
- // both macros are in system headers. If so, we trust that the system
- // did not get it wrong. This also handles cases where Clang's own
- // headers have a different spelling of certain system macros:
- // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
- // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
- //
- // FIXME: Remove the defined-in-system-headers check. clang's limits.h
- // overrides the system limits.h's macros, so there's no conflict here.
- if (NewMI != PrevMI &&
- !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) &&
- !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this))
- break;
-
- // The previous definition is the same as this one (or both are defined in
- // system modules so we can assume they're equivalent); we don't need to
- // track it any more.
- Prev->pop_back();
- }
-
- if (!Prev->empty())
- MD->setAmbiguous(true);
-
- PP.appendMacroDirective(II, MD);
+ if (Latest)
+ PP.setLoadedMacroDirective(II, Latest);
}
ASTReader::InputFileInfo
@@ -2426,6 +2195,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
}
+ case KNOWN_MODULE_FILES:
+ break;
+
case LANGUAGE_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
// FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
@@ -2440,7 +2212,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case TARGET_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
- ParseTargetOptions(Record, Complain, *Listener) &&
+ ParseTargetOptions(Record, Complain, *Listener,
+ AllowCompatibleConfigurationMismatch) &&
!DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
@@ -2543,7 +2316,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case INPUT_FILE_OFFSETS:
NumInputs = Record[0];
NumUserInputs = Record[1];
- F.InputFileOffsets = (const uint32_t *)Blob.data();
+ F.InputFileOffsets =
+ (const llvm::support::unaligned_uint64_t *)Blob.data();
F.InputFilesLoaded.resize(NumInputs);
break;
}
@@ -2795,6 +2569,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case EAGERLY_DESERIALIZED_DECLS:
+ // FIXME: Skip reading this record if our ASTConsumer doesn't care
+ // about "interesting" decls (for instance, if we're building a module).
for (unsigned I = 0, N = Record.size(); I != N; ++I)
EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I]));
break;
@@ -2859,11 +2635,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
- case LOCALLY_SCOPED_EXTERN_C_DECLS:
- for (unsigned I = 0, N = Record.size(); I != N; ++I)
- LocallyScopedExternCDecls.push_back(getGlobalDeclID(F, Record[I]));
- break;
-
case SELECTOR_OFFSETS: {
F.SelectorOffsets = (const uint32_t *)Blob.data();
F.LocalNumSelectors = Record[0];
@@ -3066,11 +2837,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
- case DYNAMIC_CLASSES:
- for (unsigned I = 0, N = Record.size(); I != N; ++I)
- DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));
- break;
-
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
Error("Invalid existing PendingInstantiations");
@@ -3172,16 +2938,26 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case OBJC_CATEGORIES:
F.ObjCCategories.swap(Record);
break;
-
+
case CXX_BASE_SPECIFIER_OFFSETS: {
if (F.LocalNumCXXBaseSpecifiers != 0) {
Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
return Failure;
}
-
+
F.LocalNumCXXBaseSpecifiers = Record[0];
F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data();
- NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
+ break;
+ }
+
+ case CXX_CTOR_INITIALIZERS_OFFSETS: {
+ if (F.LocalNumCXXCtorInitializers != 0) {
+ Error("duplicate CXX_CTOR_INITIALIZERS_OFFSETS record in AST file");
+ return Failure;
+ }
+
+ F.LocalNumCXXCtorInitializers = Record[0];
+ F.CXXCtorInitializersOffsets = (const uint32_t *)Blob.data();
break;
}
@@ -3256,6 +3032,18 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ReadSourceLocation(F, Record, I).getRawEncoding());
}
break;
+ case DELETE_EXPRS_TO_ANALYZE:
+ for (unsigned I = 0, N = Record.size(); I != N;) {
+ DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++]));
+ const uint64_t Count = Record[I++];
+ DelayedDeleteExprs.push_back(Count);
+ for (uint64_t C = 0; C < Count; ++C) {
+ DelayedDeleteExprs.push_back(ReadSourceLocation(F, Record, I).getRawEncoding());
+ bool IsArrayForm = Record[I++] == 1;
+ DelayedDeleteExprs.push_back(IsArrayForm);
+ }
+ }
+ break;
case IMPORTED_MODULES: {
if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) {
@@ -3288,16 +3076,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case MERGED_DECLARATIONS: {
- for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
- GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
- SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
- for (unsigned N = Record[Idx++]; N > 0; --N)
- Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
- }
- break;
- }
-
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
@@ -3322,11 +3100,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case MACRO_TABLE: {
- // FIXME: Not used yet.
- break;
- }
-
case LATE_PARSED_TEMPLATE: {
LateParsedTemplates.append(Record.begin(), Record.end());
break;
@@ -3472,10 +3245,9 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
}
}
-void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
- bool FromFinalization) {
- // FIXME: Only do this if Owner->NameVisibility == AllVisible.
- for (Decl *D : Names.HiddenDecls) {
+void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
+ assert(Owner->NameVisibility != Module::Hidden && "nothing to make visible?");
+ for (Decl *D : Names) {
bool wasHidden = D->Hidden;
D->Hidden = false;
@@ -3485,22 +3257,11 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
}
}
}
-
- assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) &&
- "nothing to make visible?");
- for (const auto &Macro : Names.HiddenMacros) {
- if (FromFinalization)
- PP.appendMacroDirective(Macro.first,
- Macro.second->import(PP, SourceLocation()));
- else
- installImportedMacro(Macro.first, Macro.second, Owner);
- }
}
void ASTReader::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility,
- SourceLocation ImportLoc,
- bool Complain) {
+ SourceLocation ImportLoc) {
llvm::SmallPtrSet<Module *, 4> Visited;
SmallVector<Module *, 4> Stack;
Stack.push_back(Mod);
@@ -3519,9 +3280,6 @@ void ASTReader::makeModuleVisible(Module *Mod,
}
// Update the module's name visibility.
- if (NameVisibility >= Module::MacrosVisible &&
- Mod->NameVisibility < Module::MacrosVisible)
- Mod->MacroVisibilityLoc = ImportLoc;
Mod->NameVisibility = NameVisibility;
// If we've already deserialized any names from this module,
@@ -3530,8 +3288,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
if (Hidden != HiddenNamesMap.end()) {
auto HiddenNames = std::move(*Hidden);
HiddenNamesMap.erase(Hidden);
- makeNamesVisible(HiddenNames.second, HiddenNames.first,
- /*FromFinalization*/false);
+ makeNamesVisible(HiddenNames.second, HiddenNames.first);
assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() &&
"making names visible added hidden names");
}
@@ -3545,20 +3302,6 @@ void ASTReader::makeModuleVisible(Module *Mod,
if (Visited.insert(Exported).second)
Stack.push_back(Exported);
}
-
- // Detect any conflicts.
- if (Complain) {
- assert(ImportLoc.isValid() && "Missing import location");
- for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) {
- if (Mod->Conflicts[I].Other->NameVisibility >= NameVisibility) {
- Diag(ImportLoc, diag::warn_module_conflict)
- << Mod->getFullModuleName()
- << Mod->Conflicts[I].Other->getFullModuleName()
- << Mod->Conflicts[I].Message;
- // FIXME: Need note where the other module was imported.
- }
- }
- }
}
}
@@ -3717,7 +3460,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
case UnresolvedModuleRef::Import:
if (ResolvedMod)
- Unresolved.Mod->Imports.push_back(ResolvedMod);
+ Unresolved.Mod->Imports.insert(ResolvedMod);
continue;
case UnresolvedModuleRef::Export:
@@ -3785,6 +3528,14 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
+static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
+ return Stream.Read(8) == 'C' &&
+ Stream.Read(8) == 'P' &&
+ Stream.Read(8) == 'C' &&
+ Stream.Read(8) == 'H';
+}
+
ASTReader::ASTReadResult
ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type,
@@ -3850,14 +3601,12 @@ ASTReader::ReadASTCore(StringRef FileName,
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
+ PCHContainerOps.ExtractPCH(F.Buffer->getMemBufferRef(), F.StreamFile);
Stream.init(&F.StreamFile);
F.SizeInBits = F.Buffer->getBufferSize() * 8;
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream)) {
Diag(diag::err_not_a_pch_file) << FileName;
return Failure;
}
@@ -3924,7 +3673,7 @@ ASTReader::ReadASTCore(StringRef FileName,
return Success;
}
-void ASTReader::InitializeContext() {
+void ASTReader::InitializeContext() {
// If there's a listener, notify them that we "read" the translation unit.
if (DeserializationListener)
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
@@ -4047,24 +3796,19 @@ void ASTReader::InitializeContext() {
}
// Re-export any modules that were imported by a non-module AST file.
- // FIXME: This does not make macro-only imports visible again. It also doesn't
- // make #includes mapped to module imports visible.
+ // FIXME: This does not make macro-only imports visible again.
for (auto &Import : ImportedModules) {
- if (Module *Imported = getSubmodule(Import.ID))
+ if (Module *Imported = getSubmodule(Import.ID)) {
makeModuleVisible(Imported, Module::AllVisible,
- /*ImportLoc=*/Import.ImportLoc,
- /*Complain=*/false);
+ /*ImportLoc=*/Import.ImportLoc);
+ PP.makeModuleVisible(Imported, Import.ImportLoc);
+ }
}
ImportedModules.clear();
}
void ASTReader::finalizeForWriting() {
- while (!HiddenNamesMap.empty()) {
- auto HiddenNames = std::move(*HiddenNamesMap.begin());
- HiddenNamesMap.erase(HiddenNamesMap.begin());
- makeNamesVisible(HiddenNames.second, HiddenNames.first,
- /*FromFinalization*/true);
- }
+ // Nothing to do for now.
}
/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
@@ -4097,14 +3841,12 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
}
}
+/// \brief Reads and return the signature record from \p StreamFile's control
+/// block, or else returns 0.
static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
BitstreamCursor Stream(StreamFile);
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream))
return 0;
- }
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
@@ -4128,9 +3870,9 @@ static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
/// \brief Retrieve the name of the original source file name
/// directly from the AST file, without actually loading the AST
/// file.
-std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
- FileManager &FileMgr,
- DiagnosticsEngine &Diags) {
+std::string ASTReader::getOriginalSourceFile(
+ const std::string &ASTFileName, FileManager &FileMgr,
+ const PCHContainerOperations &PCHContainerOps, DiagnosticsEngine &Diags) {
// Open the AST file.
auto Buffer = FileMgr.getBufferForFile(ASTFileName);
if (!Buffer) {
@@ -4141,15 +3883,11 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
// Initialize the stream
llvm::BitstreamReader StreamFile;
- StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
- (const unsigned char *)(*Buffer)->getBufferEnd());
+ PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream)) {
Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
return std::string();
}
@@ -4184,16 +3922,19 @@ namespace {
const LangOptions &ExistingLangOpts;
const TargetOptions &ExistingTargetOpts;
const PreprocessorOptions &ExistingPPOpts;
+ std::string ExistingModuleCachePath;
FileManager &FileMgr;
-
+
public:
SimplePCHValidator(const LangOptions &ExistingLangOpts,
const TargetOptions &ExistingTargetOpts,
const PreprocessorOptions &ExistingPPOpts,
+ StringRef ExistingModuleCachePath,
FileManager &FileMgr)
: ExistingLangOpts(ExistingLangOpts),
ExistingTargetOpts(ExistingTargetOpts),
ExistingPPOpts(ExistingPPOpts),
+ ExistingModuleCachePath(ExistingModuleCachePath),
FileMgr(FileMgr)
{
}
@@ -4203,9 +3944,17 @@ namespace {
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
AllowCompatibleDifferences);
}
- bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) override {
- return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr);
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
+ return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr,
+ AllowCompatibleDifferences);
+ }
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) override {
+ return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ ExistingModuleCachePath,
+ nullptr, ExistingLangOpts);
}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool Complain,
@@ -4216,10 +3965,13 @@ namespace {
};
}
-bool ASTReader::readASTFileControlBlock(StringRef Filename,
- FileManager &FileMgr,
- ASTReaderListener &Listener) {
+bool ASTReader::readASTFileControlBlock(
+ StringRef Filename, FileManager &FileMgr,
+ const PCHContainerOperations &PCHContainerOps,
+ ASTReaderListener &Listener) {
// Open the AST file.
+ // FIXME: This allows use of the VFS; we do not allow use of the
+ // VFS when actually loading a module.
auto Buffer = FileMgr.getBufferForFile(Filename);
if (!Buffer) {
return true;
@@ -4227,17 +3979,12 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
// Initialize the stream
llvm::BitstreamReader StreamFile;
- StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
- (const unsigned char *)(*Buffer)->getBufferEnd());
+ PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream))
return true;
- }
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
@@ -4310,7 +4057,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
break;
case TARGET_OPTIONS:
- if (ParseTargetOptions(Record, false, Listener))
+ if (ParseTargetOptions(Record, false, Listener,
+ /*AllowCompatibleConfigurationMismatch*/ false))
return true;
break;
@@ -4343,7 +4091,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
unsigned NumInputFiles = Record[0];
unsigned NumUserFiles = Record[1];
- const uint32_t *InputFileOffs = (const uint32_t *)Blob.data();
+ const uint64_t *InputFileOffs = (const uint64_t *)Blob.data();
for (unsigned I = 0; I != NumInputFiles; ++I) {
// Go find this input file.
bool isSystemFile = I >= NumUserFiles;
@@ -4389,6 +4137,20 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
break;
}
+ case KNOWN_MODULE_FILES: {
+ // Known-but-not-technically-used module files are treated as imports.
+ if (!NeedsImports)
+ break;
+
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(Filename, ModuleDir);
+ Listener.visitImport(Filename);
+ }
+ break;
+ }
+
default:
// No other validation to perform.
break;
@@ -4396,14 +4158,15 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
}
}
-
-bool ASTReader::isAcceptableASTFile(StringRef Filename,
- FileManager &FileMgr,
- const LangOptions &LangOpts,
- const TargetOptions &TargetOpts,
- const PreprocessorOptions &PPOpts) {
- SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
- return !readASTFileControlBlock(Filename, FileMgr, validator);
+bool ASTReader::isAcceptableASTFile(
+ StringRef Filename, FileManager &FileMgr,
+ const PCHContainerOperations &PCHContainerOps, const LangOptions &LangOpts,
+ const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts,
+ std::string ExistingModuleCachePath) {
+ SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
+ ExistingModuleCachePath, FileMgr);
+ return !readASTFileControlBlock(Filename, FileMgr, PCHContainerOps,
+ validator);
}
ASTReader::ASTReadResult
@@ -4508,6 +4271,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->setASTFile(F.File);
}
+ CurrentModule->Signature = F.Signature;
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
CurrentModule->IsExternC = IsExternC;
@@ -4529,13 +4293,19 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_UMBRELLA_HEADER: {
- if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) {
+ std::string Filename = Blob;
+ ResolveImportedPath(F, Filename);
+ if (auto *Umbrella = PP.getFileManager().getFile(Filename)) {
if (!CurrentModule->getUmbrellaHeader())
- ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
- else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
- Error("mismatched umbrella headers in submodule");
- return OutOfDate;
+ ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) {
+ // This can be a spurious difference caused by changing the VFS to
+ // point to a different copy of the file, and it is too late to
+ // to rebuild safely.
+ // FIXME: If we wrote the virtual paths instead of the 'real' paths,
+ // after input file validation only real problems would remain and we
+ // could just error. For now, assume it's okay.
+ break;
}
}
break;
@@ -4561,11 +4331,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_UMBRELLA_DIR: {
- if (const DirectoryEntry *Umbrella
- = PP.getFileManager().getDirectory(Blob)) {
+ std::string Dirname = Blob;
+ ResolveImportedPath(F, Dirname);
+ if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) {
if (!CurrentModule->getUmbrellaDir())
- ModMap.setUmbrellaDir(CurrentModule, Umbrella);
- else if (CurrentModule->getUmbrellaDir() != Umbrella) {
+ ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella directories in submodule");
return OutOfDate;
@@ -4675,15 +4446,14 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
LangOpts.Sanitize.set(SanitizerKind::ID, Record[Idx++]);
#include "clang/Basic/Sanitizers.def"
+ for (unsigned N = Record[Idx++]; N; --N)
+ LangOpts.ModuleFeatures.push_back(ReadString(Record, Idx));
+
ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
-
- unsigned Length = Record[Idx++];
- LangOpts.CurrentModule.assign(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- Idx += Length;
+ LangOpts.CurrentModule = ReadString(Record, Idx);
// Comment options.
for (unsigned N = Record[Idx++]; N; --N) {
@@ -4696,9 +4466,9 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
AllowCompatibleDifferences);
}
-bool ASTReader::ParseTargetOptions(const RecordData &Record,
- bool Complain,
- ASTReaderListener &Listener) {
+bool ASTReader::ParseTargetOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences) {
unsigned Idx = 0;
TargetOptions TargetOpts;
TargetOpts.Triple = ReadString(Record, Idx);
@@ -4711,7 +4481,8 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record,
TargetOpts.Features.push_back(ReadString(Record, Idx));
}
- return Listener.ReadTargetOptions(TargetOpts, Complain);
+ return Listener.ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
@@ -4753,16 +4524,15 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
= static_cast<frontend::IncludeDirGroup>(Record[Idx++]);
bool IsFramework = Record[Idx++];
bool IgnoreSysRoot = Record[Idx++];
- HSOpts.UserEntries.push_back(
- HeaderSearchOptions::Entry(Path, Group, IsFramework, IgnoreSysRoot));
+ HSOpts.UserEntries.emplace_back(std::move(Path), Group, IsFramework,
+ IgnoreSysRoot);
}
// System header prefixes.
for (unsigned N = Record[Idx++]; N; --N) {
std::string Prefix = ReadString(Record, Idx);
bool IsSystemHeader = Record[Idx++];
- HSOpts.SystemHeaderPrefixes.push_back(
- HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));
+ HSOpts.SystemHeaderPrefixes.emplace_back(std::move(Prefix), IsSystemHeader);
}
HSOpts.ResourceDir = ReadString(Record, Idx);
@@ -4773,8 +4543,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
HSOpts.UseStandardSystemIncludes = Record[Idx++];
HSOpts.UseStandardCXXIncludes = Record[Idx++];
HSOpts.UseLibcxx = Record[Idx++];
+ std::string SpecificModuleCachePath = ReadString(Record, Idx);
- return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
+ return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain);
}
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
@@ -4823,21 +4595,22 @@ ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
return std::make_pair(M, LocalIndex);
}
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+llvm::iterator_range<PreprocessingRecord::iterator>
ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())
return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,
Mod.NumPreprocessedEntities);
- return std::make_pair(PreprocessingRecord::iterator(),
- PreprocessingRecord::iterator());
+ return llvm::make_range(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
}
-std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
+llvm::iterator_range<ASTReader::ModuleDeclIterator>
ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
- return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
- ModuleDeclIterator(this, &Mod,
- Mod.FileSortedDecls + Mod.NumFileSortedDecls));
+ return llvm::make_range(
+ ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
+ ModuleDeclIterator(this, &Mod,
+ Mod.FileSortedDecls + Mod.NumFileSortedDecls));
}
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
@@ -4873,13 +4646,14 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
case PPD_MACRO_EXPANSION: {
bool isBuiltin = Record[0];
IdentifierInfo *Name = nullptr;
- MacroDefinition *Def = nullptr;
+ MacroDefinitionRecord *Def = nullptr;
if (isBuiltin)
Name = getLocalIdentifier(M, Record[1]);
else {
- PreprocessedEntityID
- GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);
- Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));
+ PreprocessedEntityID GlobalID =
+ getGlobalPreprocessedEntityID(M, Record[1]);
+ Def = cast<MacroDefinitionRecord>(
+ PPRec.getLoadedPreprocessedEntity(GlobalID - 1));
}
MacroExpansion *ME;
@@ -4895,8 +4669,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
// Decode the identifier info and then check again; if the macro is
// still defined and associated with the identifier,
IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
- MacroDefinition *MD
- = new (PPRec) MacroDefinition(II, Range);
+ MacroDefinitionRecord *MD = new (PPRec) MacroDefinitionRecord(II, Range);
if (DeserializationListener)
DeserializationListener->MacroDefinitionRead(PPID, MD);
@@ -5492,11 +5265,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
case TYPE_OBJC_OBJECT: {
unsigned Idx = 0;
QualType Base = readType(*Loc.F, Record, Idx);
+ unsigned NumTypeArgs = Record[Idx++];
+ SmallVector<QualType, 4> TypeArgs;
+ for (unsigned I = 0; I != NumTypeArgs; ++I)
+ TypeArgs.push_back(readType(*Loc.F, Record, Idx));
unsigned NumProtos = Record[Idx++];
SmallVector<ObjCProtocolDecl*, 4> Protos;
for (unsigned I = 0; I != NumProtos; ++I)
Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
- return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
+ bool IsKindOf = Record[Idx++];
+ return Context.getObjCObjectType(Base, TypeArgs, Protos, IsKindOf);
}
case TYPE_OBJC_OBJECT_POINTER: {
@@ -5875,8 +5653,12 @@ void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
}
void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
TL.setHasBaseTypeAsWritten(Record[Idx++]);
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgsLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgsRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
+ TL.setTypeArgTInfo(i, Reader.GetTypeSourceInfo(F, Record, Idx));
+ TL.setProtocolLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setProtocolRAngleLoc(ReadSourceLocation(Record, Idx));
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
}
@@ -6081,6 +5863,12 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) {
return GetDecl(ID);
}
+template<typename TemplateSpecializationDecl>
+static void completeRedeclChainForTemplateSpecialization(Decl *D) {
+ if (auto *TSD = dyn_cast<TemplateSpecializationDecl>(D))
+ TSD->getSpecializedTemplate()->LoadLazySpecializations();
+}
+
void ASTReader::CompleteRedeclChain(const Decl *D) {
if (NumCurrentElementsDeserializing) {
// We arrange to not care about the complete redeclaration chain while we're
@@ -6114,6 +5902,47 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
D->getDeclContext()->decls_begin();
}
}
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ CTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
+ VTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (auto *Template = FD->getPrimaryTemplate())
+ Template->LoadLazySpecializations();
+ }
+}
+
+uint64_t ASTReader::ReadCXXCtorInitializersRef(ModuleFile &M,
+ const RecordData &Record,
+ unsigned &Idx) {
+ if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXCtorInitializers) {
+ Error("malformed AST file: missing C++ ctor initializers");
+ return 0;
+ }
+
+ unsigned LocalID = Record[Idx++];
+ return getGlobalBitOffset(M, M.CXXCtorInitializersOffsets[LocalID - 1]);
+}
+
+CXXCtorInitializer **
+ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ RecordLocation Loc = getLocalBitOffset(Offset);
+ BitstreamCursor &Cursor = Loc.F->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Loc.Offset);
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record);
+ if (RecCode != DECL_CXX_CTOR_INITIALIZERS) {
+ Error("malformed AST file: missing C++ ctor initializers");
+ return nullptr;
+ }
+
+ unsigned Idx = 0;
+ return ReadCXXCtorInitializers(*Loc.F, Record, Idx);
}
uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M,
@@ -6165,9 +5994,12 @@ ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
ModuleFile &M) const {
- GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
- return &M == I->second;
+ // Predefined decls aren't from any module.
+ if (ID < NUM_PREDEF_DECL_IDS)
+ return false;
+
+ return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
+ ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls;
}
ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) {
@@ -6197,39 +6029,55 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
return ReadSourceLocation(*Rec.F, RawLocation);
}
-Decl *ASTReader::GetExistingDecl(DeclID ID) {
- if (ID < NUM_PREDEF_DECL_IDS) {
- switch ((PredefinedDeclIDs)ID) {
- case PREDEF_DECL_NULL_ID:
- return nullptr;
+static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
+ switch (ID) {
+ case PREDEF_DECL_NULL_ID:
+ return nullptr;
+
+ case PREDEF_DECL_TRANSLATION_UNIT_ID:
+ return Context.getTranslationUnitDecl();
- case PREDEF_DECL_TRANSLATION_UNIT_ID:
- return Context.getTranslationUnitDecl();
+ case PREDEF_DECL_OBJC_ID_ID:
+ return Context.getObjCIdDecl();
- case PREDEF_DECL_OBJC_ID_ID:
- return Context.getObjCIdDecl();
+ case PREDEF_DECL_OBJC_SEL_ID:
+ return Context.getObjCSelDecl();
- case PREDEF_DECL_OBJC_SEL_ID:
- return Context.getObjCSelDecl();
+ case PREDEF_DECL_OBJC_CLASS_ID:
+ return Context.getObjCClassDecl();
- case PREDEF_DECL_OBJC_CLASS_ID:
- return Context.getObjCClassDecl();
+ case PREDEF_DECL_OBJC_PROTOCOL_ID:
+ return Context.getObjCProtocolDecl();
- case PREDEF_DECL_OBJC_PROTOCOL_ID:
- return Context.getObjCProtocolDecl();
+ case PREDEF_DECL_INT_128_ID:
+ return Context.getInt128Decl();
- case PREDEF_DECL_INT_128_ID:
- return Context.getInt128Decl();
+ case PREDEF_DECL_UNSIGNED_INT_128_ID:
+ return Context.getUInt128Decl();
- case PREDEF_DECL_UNSIGNED_INT_128_ID:
- return Context.getUInt128Decl();
+ case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
+ return Context.getObjCInstanceTypeDecl();
- case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
- return Context.getObjCInstanceTypeDecl();
+ case PREDEF_DECL_BUILTIN_VA_LIST_ID:
+ return Context.getBuiltinVaListDecl();
- case PREDEF_DECL_BUILTIN_VA_LIST_ID:
- return Context.getBuiltinVaListDecl();
+ case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
+ return Context.getExternCContextDecl();
+ }
+ llvm_unreachable("PredefinedDeclIDs unknown enum value");
+}
+
+Decl *ASTReader::GetExistingDecl(DeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS) {
+ Decl *D = getPredefinedDecl(Context, (PredefinedDeclIDs)ID);
+ if (D) {
+ // Track that we have merged the declaration with ID \p ID into the
+ // pre-existing predefined declaration \p D.
+ auto &Merged = KeyDecls[D->getCanonicalDecl()];
+ if (Merged.empty())
+ Merged.push_back(ID);
}
+ return D;
}
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
@@ -6326,10 +6174,7 @@ namespace {
PredefsVisited[I] = false;
}
- static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
- if (Preorder)
- return false;
-
+ static bool visitPostorder(ModuleFile &M, void *UserData) {
FindExternalLexicalDeclsVisitor *This
= static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
@@ -6371,7 +6216,8 @@ ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
// There might be lexical decls in multiple modules, for the TU at
// least. Walk all of the modules in the order they were loaded.
FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
- ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
+ ModuleMgr.visitDepthFirst(
+ nullptr, &FindExternalLexicalDeclsVisitor::visitPostorder, &Visitor);
++NumLexicalDeclContextsRead;
return ELR_Success;
}
@@ -6452,6 +6298,27 @@ void ASTReader::FindFileRegionDecls(FileID File,
Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
}
+/// \brief Retrieve the "definitive" module file for the definition of the
+/// given declaration context, if there is one.
+///
+/// The "definitive" module file is the only place where we need to look to
+/// find information about the declarations within the given declaration
+/// context. For example, C++ and Objective-C classes, C structs/unions, and
+/// Objective-C protocols, categories, and extensions are all defined in a
+/// single place in the source code, so they have definitive module files
+/// associated with them. C++ namespaces, on the other hand, can have
+/// definitions in multiple different module files.
+///
+/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
+/// NDEBUG checking.
+static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
+ ASTReader &Reader) {
+ if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
+ return Reader.getOwningModuleFile(cast<Decl>(DefDC));
+
+ return nullptr;
+}
+
namespace {
/// \brief ModuleFile visitor used to perform name lookup into a
/// declaration context.
@@ -6459,15 +6326,38 @@ namespace {
ASTReader &Reader;
ArrayRef<const DeclContext *> Contexts;
DeclarationName Name;
+ ASTDeclContextNameLookupTrait::DeclNameKey NameKey;
+ unsigned NameHash;
SmallVectorImpl<NamedDecl *> &Decls;
+ llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet;
public:
DeclContextNameLookupVisitor(ASTReader &Reader,
- ArrayRef<const DeclContext *> Contexts,
DeclarationName Name,
- SmallVectorImpl<NamedDecl *> &Decls)
- : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
+ SmallVectorImpl<NamedDecl *> &Decls,
+ llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet)
+ : Reader(Reader), Name(Name),
+ NameKey(ASTDeclContextNameLookupTrait::GetInternalKey(Name)),
+ NameHash(ASTDeclContextNameLookupTrait::ComputeHash(NameKey)),
+ Decls(Decls), DeclSet(DeclSet) {}
+
+ void visitContexts(ArrayRef<const DeclContext*> Contexts) {
+ if (Contexts.empty())
+ return;
+ this->Contexts = Contexts;
+
+ // If we can definitively determine which module file to look into,
+ // only look there. Otherwise, look in all module files.
+ ModuleFile *Definitive;
+ if (Contexts.size() == 1 &&
+ (Definitive = getDefinitiveModuleFileFor(Contexts[0], Reader))) {
+ visit(*Definitive, this);
+ } else {
+ Reader.getModuleManager().visit(&visit, this);
+ }
+ }
+ private:
static bool visit(ModuleFile &M, void *UserData) {
DeclContextNameLookupVisitor *This
= static_cast<DeclContextNameLookupVisitor *>(UserData);
@@ -6492,7 +6382,7 @@ namespace {
ASTDeclContextNameLookupTable *LookupTable =
Info->second.NameLookupTableData;
ASTDeclContextNameLookupTable::iterator Pos
- = LookupTable->find(This->Name);
+ = LookupTable->find_hashed(This->NameKey, This->NameHash);
if (Pos == LookupTable->end())
return false;
@@ -6515,7 +6405,8 @@ namespace {
// Record this declaration.
FoundAnything = true;
- This->Decls.push_back(ND);
+ if (This->DeclSet.insert(ND).second)
+ This->Decls.push_back(ND);
}
return FoundAnything;
@@ -6523,27 +6414,6 @@ namespace {
};
}
-/// \brief Retrieve the "definitive" module file for the definition of the
-/// given declaration context, if there is one.
-///
-/// The "definitive" module file is the only place where we need to look to
-/// find information about the declarations within the given declaration
-/// context. For example, C++ and Objective-C classes, C structs/unions, and
-/// Objective-C protocols, categories, and extensions are all defined in a
-/// single place in the source code, so they have definitive module files
-/// associated with them. C++ namespaces, on the other hand, can have
-/// definitions in multiple different module files.
-///
-/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
-/// NDEBUG checking.
-static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
- ASTReader &Reader) {
- if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
- return Reader.getOwningModuleFile(cast<Decl>(DefDC));
-
- return nullptr;
-}
-
bool
ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
@@ -6555,6 +6425,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Deserializing LookupResults(this);
SmallVector<NamedDecl *, 64> Decls;
+ llvm::SmallPtrSet<NamedDecl*, 64> DeclSet;
// Compute the declaration contexts we need to look into. Multiple such
// declaration contexts occur when two declaration contexts from disjoint
@@ -6564,47 +6435,29 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Contexts.push_back(DC);
if (DC->isNamespace()) {
- auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Merged != MergedDecls.end()) {
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ auto Key = KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Key != KeyDecls.end()) {
+ for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
}
}
- auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) {
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
-
- // If we can definitively determine which module file to look into,
- // only look there. Otherwise, look in all module files.
- ModuleFile *Definitive;
- if (Contexts.size() == 1 &&
- (Definitive = getDefinitiveModuleFileFor(Contexts[0], *this))) {
- DeclContextNameLookupVisitor::visit(*Definitive, &Visitor);
- } else {
- ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
- }
- };
-
- LookUpInContexts(Contexts);
+ DeclContextNameLookupVisitor Visitor(*this, Name, Decls, DeclSet);
+ Visitor.visitContexts(Contexts);
// If this might be an implicit special member function, then also search
// all merged definitions of the surrounding class. We need to search them
// individually, because finding an entity in one of them doesn't imply that
// we can't find a different entity in another one.
if (isa<CXXRecordDecl>(DC)) {
- auto Kind = Name.getNameKind();
- if (Kind == DeclarationName::CXXConstructorName ||
- Kind == DeclarationName::CXXDestructorName ||
- (Kind == DeclarationName::CXXOperatorName &&
- Name.getCXXOverloadedOperator() == OO_Equal)) {
- auto Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end()) {
- for (unsigned I = 0; I != Merged->second.size(); ++I) {
- LookUpInContexts(Merged->second[I]);
- // We might have just added some more merged lookups. If so, our
- // iterator is now invalid, so grab a fresh one before continuing.
- Merged = MergedLookups.find(DC);
- }
+ auto Merged = MergedLookups.find(DC);
+ if (Merged != MergedLookups.end()) {
+ for (unsigned I = 0; I != Merged->second.size(); ++I) {
+ const DeclContext *Context = Merged->second[I];
+ Visitor.visitContexts(Context);
+ // We might have just added some more merged lookups. If so, our
+ // iterator is now invalid, so grab a fresh one before continuing.
+ Merged = MergedLookups.find(DC);
}
}
}
@@ -6621,6 +6474,7 @@ namespace {
ASTReader &Reader;
SmallVectorImpl<const DeclContext *> &Contexts;
DeclsMap &Decls;
+ llvm::SmallPtrSet<NamedDecl *, 256> DeclSet;
bool VisitAll;
public:
@@ -6665,7 +6519,8 @@ namespace {
// Record this declaration.
FoundAnything = true;
- This->Decls[ND->getDeclName()].push_back(ND);
+ if (This->DeclSet.insert(ND).second)
+ This->Decls[ND->getDeclName()].push_back(ND);
}
}
@@ -6687,11 +6542,11 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
Contexts.push_back(DC);
if (DC->isNamespace()) {
- MergedDeclsMap::iterator Merged
- = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Merged != MergedDecls.end()) {
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ KeyDeclsMap::iterator Key =
+ KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Key != KeyDecls.end()) {
+ for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
}
}
@@ -6731,6 +6586,12 @@ void ASTReader::PassInterestingDeclsToConsumer() {
SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
true);
+ // Ensure that we've loaded all potentially-interesting declarations
+ // that need to be eagerly loaded.
+ for (auto ID : EagerlyDeserializedDecls)
+ GetDecl(ID);
+ EagerlyDeserializedDecls.clear();
+
while (!InterestingDecls.empty()) {
Decl *D = InterestingDecls.front();
InterestingDecls.pop_front();
@@ -6749,17 +6610,11 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;
- if (!Consumer)
- return;
-
- for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) {
- // Force deserialization of this decl, which will cause it to be queued for
- // passing to the consumer.
- GetDecl(EagerlyDeserializedDecls[I]);
- }
- EagerlyDeserializedDecls.clear();
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
- PassInterestingDeclsToConsumer();
+ if (DeserializationListener)
+ DeserializationListener->ReaderInitialized(this);
}
void ASTReader::PrintStats() {
@@ -7195,6 +7050,21 @@ void ASTReader::ReadUndefinedButUsed(
}
}
+void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) {
+ for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) {
+ FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++]));
+ uint64_t Count = DelayedDeleteExprs[Idx++];
+ for (uint64_t C = 0; C < Count; ++C) {
+ SourceLocation DeleteLoc =
+ SourceLocation::getFromRawEncoding(DelayedDeleteExprs[Idx++]);
+ const bool IsArrayForm = DelayedDeleteExprs[Idx++];
+ Exprs[FD].push_back(std::make_pair(DeleteLoc, IsArrayForm));
+ }
+ }
+}
+
void ASTReader::ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs) {
for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
@@ -7237,16 +7107,6 @@ void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {
ExtVectorDecls.clear();
}
-void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
- for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
- CXXRecordDecl *D
- = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));
- if (D)
- Decls.push_back(D);
- }
- DynamicClasses.clear();
-}
-
void ASTReader::ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N;
@@ -7259,17 +7119,6 @@ void ASTReader::ReadUnusedLocalTypedefNameCandidates(
UnusedLocalTypedefNameCandidates.clear();
}
-void
-ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) {
- for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) {
- NamedDecl *D
- = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternCDecls[I]));
- if (D)
- Decls.push_back(D);
- }
- LocallyScopedExternCDecls.clear();
-}
-
void ASTReader::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
if (ReferencedSelectorsData.empty())
@@ -7333,7 +7182,7 @@ void ASTReader::ReadPendingInstantiations(
}
void ASTReader::ReadLateParsedTemplates(
- llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N;
/* In loop */) {
FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++]));
@@ -7349,7 +7198,7 @@ void ASTReader::ReadLateParsedTemplates(
for (unsigned T = 0; T < TokN; ++T)
LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx));
- LPTMap[FD] = LT;
+ LPTMap.insert(std::make_pair(FD, LT));
}
LateParsedTemplates.clear();
@@ -7535,6 +7384,37 @@ Module *ASTReader::getModule(unsigned ID) {
return getSubmodule(ID);
}
+ExternalASTSource::ASTSourceDescriptor
+ASTReader::getSourceDescriptor(const Module &M) {
+ StringRef Dir, Filename;
+ if (M.Directory)
+ Dir = M.Directory->getName();
+ if (auto *File = M.getASTFile())
+ Filename = File->getName();
+ return ASTReader::ASTSourceDescriptor{
+ M.getFullModuleName(), Dir, Filename,
+ M.Signature
+ };
+}
+
+llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
+ASTReader::getSourceDescriptor(unsigned ID) {
+ if (const Module *M = getSubmodule(ID))
+ return getSourceDescriptor(*M);
+
+ // If there is only a single PCH, return it instead.
+ // Chained PCH are not suported.
+ if (ModuleMgr.size() == 1) {
+ ModuleFile &MF = ModuleMgr.getPrimaryModule();
+ return ASTReader::ASTSourceDescriptor{
+ MF.OriginalSourceFileName, MF.OriginalDir,
+ MF.FileName,
+ MF.Signature
+ };
+ }
+ return None;
+}
+
Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
return DecodeSelector(getGlobalSelectorID(M, LocalID));
}
@@ -7840,92 +7720,89 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
return Result;
}
-std::pair<CXXCtorInitializer **, unsigned>
+CXXCtorInitializer **
ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
- CXXCtorInitializer **CtorInitializers = nullptr;
unsigned NumInitializers = Record[Idx++];
- if (NumInitializers) {
- CtorInitializers
- = new (Context) CXXCtorInitializer*[NumInitializers];
- for (unsigned i=0; i != NumInitializers; ++i) {
- TypeSourceInfo *TInfo = nullptr;
- bool IsBaseVirtual = false;
- FieldDecl *Member = nullptr;
- IndirectFieldDecl *IndirectMember = nullptr;
-
- CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
- switch (Type) {
- case CTOR_INITIALIZER_BASE:
- TInfo = GetTypeSourceInfo(F, Record, Idx);
- IsBaseVirtual = Record[Idx++];
- break;
-
- case CTOR_INITIALIZER_DELEGATING:
- TInfo = GetTypeSourceInfo(F, Record, Idx);
- break;
+ assert(NumInitializers && "wrote ctor initializers but have no inits");
+ auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers];
+ for (unsigned i = 0; i != NumInitializers; ++i) {
+ TypeSourceInfo *TInfo = nullptr;
+ bool IsBaseVirtual = false;
+ FieldDecl *Member = nullptr;
+ IndirectFieldDecl *IndirectMember = nullptr;
- case CTOR_INITIALIZER_MEMBER:
- Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
- break;
+ CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
+ switch (Type) {
+ case CTOR_INITIALIZER_BASE:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ IsBaseVirtual = Record[Idx++];
+ break;
- case CTOR_INITIALIZER_INDIRECT_MEMBER:
- IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
- break;
- }
+ case CTOR_INITIALIZER_DELEGATING:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ break;
- SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
- Expr *Init = ReadExpr(F);
- SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
- SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
- bool IsWritten = Record[Idx++];
- unsigned SourceOrderOrNumArrayIndices;
- SmallVector<VarDecl *, 8> Indices;
- if (IsWritten) {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- } else {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- Indices.reserve(SourceOrderOrNumArrayIndices);
- for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
- Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
- }
+ case CTOR_INITIALIZER_MEMBER:
+ Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
+ break;
+
+ case CTOR_INITIALIZER_INDIRECT_MEMBER:
+ IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
+ break;
+ }
- CXXCtorInitializer *BOMInit;
- if (Type == CTOR_INITIALIZER_BASE) {
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
- LParenLoc, Init, RParenLoc,
- MemberOrEllipsisLoc);
- } else if (Type == CTOR_INITIALIZER_DELEGATING) {
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
- Init, RParenLoc);
- } else if (IsWritten) {
- if (Member)
- BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc);
- else
- BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
- MemberOrEllipsisLoc, LParenLoc,
- Init, RParenLoc);
+ SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ Expr *Init = ReadExpr(F);
+ SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
+ bool IsWritten = Record[Idx++];
+ unsigned SourceOrderOrNumArrayIndices;
+ SmallVector<VarDecl *, 8> Indices;
+ if (IsWritten) {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ } else {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ Indices.reserve(SourceOrderOrNumArrayIndices);
+ for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+ Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
+ }
+
+ CXXCtorInitializer *BOMInit;
+ if (Type == CTOR_INITIALIZER_BASE) {
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init,
+ RParenLoc, MemberOrEllipsisLoc);
+ } else if (Type == CTOR_INITIALIZER_DELEGATING) {
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc);
+ } else if (IsWritten) {
+ if (Member)
+ BOMInit = new (Context) CXXCtorInitializer(
+ Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc);
+ else
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
+ } else {
+ if (IndirectMember) {
+ assert(Indices.empty() && "Indirect field improperly initialized");
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
} else {
- if (IndirectMember) {
- assert(Indices.empty() && "Indirect field improperly initialized");
- BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
- MemberOrEllipsisLoc, LParenLoc,
- Init, RParenLoc);
- } else {
- BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc,
- Indices.data(), Indices.size());
- }
+ BOMInit = CXXCtorInitializer::Create(
+ Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
}
-
- if (IsWritten)
- BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
- CtorInitializers[i] = BOMInit;
}
+
+ if (IsWritten)
+ BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
+ CtorInitializers[i] = BOMInit;
}
- return std::make_pair(CtorInitializers, NumInitializers);
+ return CtorInitializers;
}
NestedNameSpecifier *
@@ -8203,7 +8080,7 @@ void ASTReader::getInputFiles(ModuleFile &F,
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
- if (Module *M = D->getOwningModule())
+ if (Module *M = D->getImportedOwningModule())
return M->getFullModuleName();
// Otherwise, use the name of the top-level module the decl is within.
@@ -8243,9 +8120,10 @@ void ASTReader::finishPendingActions() {
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
- loadPendingDeclChain(PendingDeclChains[I]);
PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+ loadPendingDeclChain(PendingDeclChains[I]);
}
+ assert(PendingDeclChainsKnown.empty());
PendingDeclChains.clear();
// Make the most recent of the top-level declarations visible.
@@ -8298,7 +8176,12 @@ void ASTReader::finishPendingActions() {
loadDeclUpdateRecords(Update.first, Update.second);
}
}
-
+
+ // At this point, all update records for loaded decls are in place, so any
+ // fake class definitions should have become real.
+ assert(PendingFakeDefinitionData.empty() &&
+ "faked up a class definition but never saw the real one");
+
// If we deserialized any C++ or Objective-C class definitions, any
// Objective-C protocol definitions, or any redeclarable templates, make sure
// that all redeclarations point to the definitions. Note that this can only
@@ -8309,10 +8192,12 @@ void ASTReader::finishPendingActions() {
// Make sure that the TagType points at the definition.
const_cast<TagType*>(TagT)->decl = TD;
}
-
+
if (auto RD = dyn_cast<CXXRecordDecl>(D)) {
- for (auto R : RD->redecls()) {
- assert((R == D) == R->isThisDeclarationADefinition() &&
+ for (auto *R = getMostRecentExistingDecl(RD); R;
+ R = R->getPreviousDecl()) {
+ assert((R == D) ==
+ cast<CXXRecordDecl>(R)->isThisDeclarationADefinition() &&
"declaration thinks it's the definition but it isn't");
cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData;
}
@@ -8320,34 +8205,36 @@ void ASTReader::finishPendingActions() {
continue;
}
-
+
if (auto ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// Make sure that the ObjCInterfaceType points at the definition.
const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
->Decl = ID;
-
- for (auto R : ID->redecls())
- R->Data = ID->Data;
-
+
+ for (auto *R = getMostRecentExistingDecl(ID); R; R = R->getPreviousDecl())
+ cast<ObjCInterfaceDecl>(R)->Data = ID->Data;
+
continue;
}
-
+
if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) {
- for (auto R : PD->redecls())
- R->Data = PD->Data;
-
+ for (auto *R = getMostRecentExistingDecl(PD); R; R = R->getPreviousDecl())
+ cast<ObjCProtocolDecl>(R)->Data = PD->Data;
+
continue;
}
-
+
auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
- for (auto R : RTD->redecls())
- R->Common = RTD->Common;
+ for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
+ cast<RedeclarableTemplateDecl>(R)->Common = RTD->Common;
}
PendingDefinitions.clear();
// Load the bodies of any functions or methods we've encountered. We do
// this now (delayed) so that we can be sure that the declaration chains
// have been fully wired up.
+ // FIXME: There seems to be no point in delaying this, it does not depend
+ // on the redecl chains having been wired up.
for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) {
@@ -8364,6 +8251,11 @@ void ASTReader::finishPendingActions() {
MD->setLazyBody(PB->second);
}
PendingBodies.clear();
+
+ // Do some cleanup.
+ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
+ getContext().deduplicateMergedDefinitonsFor(ND);
+ PendingMergedDefinitionsToDeduplicate.clear();
}
void ASTReader::diagnoseOdrViolations() {
@@ -8440,6 +8332,10 @@ void ASTReader::diagnoseOdrViolations() {
// completed. We only really need to mark FieldDecls as invalid here.
if (!isa<TagDecl>(D))
D->setInvalidDecl();
+
+ // Ensure we don't accidentally recursively enter deserialization while
+ // we're producing our diagnostic.
+ Deserializing RecursionGuard(this);
std::string CanonDefModule =
getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
@@ -8461,6 +8357,13 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ if (OdrMergeFailures.empty())
+ return;
+
+ // Ensure we don't accidentally recursively enter deserialization while
+ // we're producing our diagnostics.
+ Deserializing RecursionGuard(this);
+
// Issue any pending ODR-failure diagnostics.
for (auto &Merge : OdrMergeFailures) {
// If we've already pointed out a specific problem with this class, don't
@@ -8503,6 +8406,11 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+void ASTReader::StartedDeserializing() {
+ if (++NumCurrentElementsDeserializing == 1 && ReadTimer.get())
+ ReadTimer->startTimer();
+}
+
void ASTReader::FinishedDeserializing() {
assert(NumCurrentElementsDeserializing &&
"FinishedDeserializing not paired with StartedDeserializing");
@@ -8514,8 +8422,22 @@ void ASTReader::FinishedDeserializing() {
--NumCurrentElementsDeserializing;
if (NumCurrentElementsDeserializing == 0) {
+ // Propagate exception specification updates along redeclaration chains.
+ while (!PendingExceptionSpecUpdates.empty()) {
+ auto Updates = std::move(PendingExceptionSpecUpdates);
+ PendingExceptionSpecUpdates.clear();
+ for (auto Update : Updates) {
+ auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
+ SemaObj->UpdateExceptionSpec(Update.second,
+ FPT->getExtProtoInfo().ExceptionSpec);
+ }
+ }
+
diagnoseOdrViolations();
+ if (ReadTimer)
+ ReadTimer->stopTimer();
+
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
if (Consumer)
@@ -8524,7 +8446,18 @@ void ASTReader::FinishedDeserializing() {
}
void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
- D = D->getMostRecentDecl();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ // Remove any fake results before adding any real ones.
+ auto It = PendingFakeLookupResults.find(II);
+ if (It != PendingFakeLookupResults.end()) {
+ for (auto *ND : PendingFakeLookupResults[II])
+ SemaObj->IdResolver.RemoveDecl(ND);
+ // FIXME: this works around module+PCH performance issue.
+ // Rather than erase the result from the map, which is O(n), just clear
+ // the vector of NamedDecls.
+ It->second.clear();
+ }
+ }
if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) {
SemaObj->TUScope->AddDecl(D);
@@ -8538,32 +8471,35 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
}
}
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot,
- bool DisableValidation, bool AllowASTWithCompilerErrors,
+ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
+ const PCHContainerOperations &PCHContainerOps,
+ StringRef isysroot, bool DisableValidation,
+ bool AllowASTWithCompilerErrors,
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
- bool UseGlobalIndex)
+ bool UseGlobalIndex,
+ std::unique_ptr<llvm::Timer> ReadTimer)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()),
- FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
- SemaObj(nullptr), PP(PP), Context(Context), Consumer(nullptr),
- ModuleMgr(PP.getFileManager()), isysroot(isysroot),
- DisableValidation(DisableValidation),
+ FileMgr(PP.getFileManager()), PCHContainerOps(PCHContainerOps),
+ Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context),
+ Consumer(nullptr), ModuleMgr(PP.getFileManager(), PCHContainerOps),
+ ReadTimer(std::move(ReadTimer)),
+ isysroot(isysroot), DisableValidation(DisableValidation),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
AllowConfigurationMismatch(AllowConfigurationMismatch),
ValidateSystemInputs(ValidateSystemInputs),
UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
- CurrSwitchCaseStmts(&SwitchCaseStmts),
- NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0),
- TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0),
- NumIdentifierLookups(0), NumIdentifierLookupHits(0), NumSelectorsRead(0),
+ CurrSwitchCaseStmts(&SwitchCaseStmts), NumSLocEntriesRead(0),
+ TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0),
+ NumMacrosRead(0), TotalNumMacros(0), NumIdentifierLookups(0),
+ NumIdentifierLookupHits(0), NumSelectorsRead(0),
NumMethodPoolEntriesRead(0), NumMethodPoolLookups(0),
NumMethodPoolHits(0), NumMethodPoolTableLookups(0),
NumMethodPoolTableHits(0), TotalNumMethodPoolEntries(0),
NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
- PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0),
- ReadingKind(Read_None) {
+ PassingDeclsToConsumer(false), ReadingKind(Read_None) {
SourceMgr.setExternalSLocEntrySource(this);
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index a783183..1a0c5b5 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -66,7 +66,12 @@ namespace clang {
serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
return Reader.ReadDeclID(F, R, I);
}
-
+
+ void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
+ for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
+ IDs.push_back(ReadDeclID(Record, Idx));
+ }
+
Decl *ReadDecl(const RecordData &R, unsigned &I) {
return Reader.ReadDecl(F, R, I);
}
@@ -103,11 +108,11 @@ namespace clang {
return Reader.getSubmodule(readSubmoduleID(R, I));
}
- void ReadCXXRecordDefinition(CXXRecordDecl *D);
+ void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
const RecordData &R, unsigned &I);
void MergeDefinitionData(CXXRecordDecl *D,
- struct CXXRecordDecl::DefinitionData &NewDD);
+ struct CXXRecordDecl::DefinitionData &&NewDD);
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
@@ -118,43 +123,47 @@ namespace clang {
/// \brief RAII class used to capture the first ID within a redeclaration
/// chain and to introduce it into the list of pending redeclaration chains
/// on destruction.
- ///
- /// The caller can choose not to introduce this ID into the list of pending
- /// redeclaration chains by calling \c suppress().
class RedeclarableResult {
ASTReader &Reader;
GlobalDeclID FirstID;
+ Decl *MergeWith;
mutable bool Owning;
+ bool IsKeyDecl;
Decl::Kind DeclKind;
-
- void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION;
-
+
+ void operator=(RedeclarableResult &) = delete;
+
public:
RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
- Decl::Kind DeclKind)
- : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { }
-
- RedeclarableResult(const RedeclarableResult &Other)
- : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) ,
- DeclKind(Other.DeclKind)
- {
+ Decl *MergeWith, Decl::Kind DeclKind,
+ bool IsKeyDecl)
+ : Reader(Reader), FirstID(FirstID), MergeWith(MergeWith),
+ Owning(true), IsKeyDecl(IsKeyDecl), DeclKind(DeclKind) {}
+
+ RedeclarableResult(RedeclarableResult &&Other)
+ : Reader(Other.Reader), FirstID(Other.FirstID),
+ MergeWith(Other.MergeWith), Owning(Other.Owning),
+ IsKeyDecl(Other.IsKeyDecl), DeclKind(Other.DeclKind) {
Other.Owning = false;
}
~RedeclarableResult() {
- if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) &&
- Reader.PendingDeclChainsKnown.insert(FirstID).second)
- Reader.PendingDeclChains.push_back(FirstID);
+ if (FirstID && Owning && isRedeclarableDeclKind(DeclKind)) {
+ auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl();
+ if (Reader.PendingDeclChainsKnown.insert(Canon).second)
+ Reader.PendingDeclChains.push_back(Canon);
+ }
}
-
+
/// \brief Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
-
- /// \brief Do not introduce this declaration ID into the set of pending
- /// declaration chains.
- void suppress() {
- Owning = false;
- }
+
+ /// \brief Is this declaration the key declaration?
+ bool isKeyDecl() const { return IsKeyDecl; }
+
+ /// \brief Get a known declaration that this should be merged with, if
+ /// any.
+ Decl *getKnownMergeTarget() const { return MergeWith; }
};
/// \brief Class used to capture the result of searching for an existing
@@ -171,7 +180,7 @@ namespace clang {
unsigned AnonymousDeclNumber;
IdentifierInfo *TypedefNameForLinkage;
- void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION;
+ void operator=(FindExistingResult&) = delete;
public:
FindExistingResult(ASTReader &Reader)
@@ -205,6 +214,8 @@ namespace clang {
operator T*() const { return dyn_cast_or_null<T>(Existing); }
};
+ static DeclContext *getPrimaryContextForMerging(ASTReader &Reader,
+ DeclContext *DC);
FindExistingResult findExisting(NamedDecl *D);
public:
@@ -216,10 +227,17 @@ namespace clang {
TypedefNameForLinkage(nullptr), HasPendingBody(false) {}
template <typename DeclT>
+ static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
+ static Decl *getMostRecentDeclImpl(...);
+ static Decl *getMostRecentDecl(Decl *D);
+
+ template <typename DeclT>
static void attachPreviousDeclImpl(ASTReader &Reader,
- Redeclarable<DeclT> *D, Decl *Previous);
+ Redeclarable<DeclT> *D, Decl *Previous,
+ Decl *Canon);
static void attachPreviousDeclImpl(ASTReader &Reader, ...);
- static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous);
+ static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous,
+ Decl *Canon);
template <typename DeclT>
static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
@@ -335,10 +353,13 @@ namespace clang {
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID);
+ DeclID DsID, bool IsKeyDecl);
+
+ ObjCTypeParamList *ReadObjCTypeParamList();
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
void VisitObjCIvarDecl(ObjCIvarDecl *D);
@@ -352,9 +373,72 @@ namespace clang {
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+
+ /// We've merged the definition \p MergedDef into the existing definition
+ /// \p Def. Ensure that \p Def is made visible whenever \p MergedDef is made
+ /// visible.
+ void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef) {
+ if (Def->isHidden()) {
+ // If MergedDef is visible or becomes visible, make the definition visible.
+ if (!MergedDef->isHidden())
+ Def->Hidden = false;
+ else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ Reader.getContext().mergeDefinitionIntoModule(
+ Def, MergedDef->getImportedOwningModule(),
+ /*NotifyListeners*/ false);
+ Reader.PendingMergedDefinitionsToDeduplicate.insert(Def);
+ } else {
+ auto SubmoduleID = MergedDef->getOwningModuleID();
+ assert(SubmoduleID && "hidden definition in no module");
+ Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)].push_back(Def);
+ }
+ }
+ }
};
}
+namespace {
+/// Iterator over the redeclarations of a declaration that have already
+/// been merged into the same redeclaration chain.
+template<typename DeclT>
+class MergedRedeclIterator {
+ DeclT *Start, *Canonical, *Current;
+public:
+ MergedRedeclIterator() : Current(nullptr) {}
+ MergedRedeclIterator(DeclT *Start)
+ : Start(Start), Canonical(nullptr), Current(Start) {}
+
+ DeclT *operator*() { return Current; }
+
+ MergedRedeclIterator &operator++() {
+ if (Current->isFirstDecl()) {
+ Canonical = Current;
+ Current = Current->getMostRecentDecl();
+ } else
+ Current = Current->getPreviousDecl();
+
+ // If we started in the merged portion, we'll reach our start position
+ // eventually. Otherwise, we'll never reach it, but the second declaration
+ // we reached was the canonical declaration, so stop when we see that one
+ // again.
+ if (Current == Start || Current == Canonical)
+ Current = nullptr;
+ return *this;
+ }
+
+ friend bool operator!=(const MergedRedeclIterator &A,
+ const MergedRedeclIterator &B) {
+ return A.Current != B.Current;
+ }
+};
+}
+template<typename DeclT>
+llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
+ return llvm::iterator_range<MergedRedeclIterator<DeclT>>(
+ MergedRedeclIterator<DeclT>(D),
+ MergedRedeclIterator<DeclT>());
+}
+
uint64_t ASTDeclReader::GetCurrentCursorOffset() {
return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset;
}
@@ -390,9 +474,14 @@ void ASTDeclReader::Visit(Decl *D) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
// We only read it if FD doesn't already have a body (e.g., from another
// module).
- // FIXME: Also consider = default and = delete.
// FIXME: Can we diagnose ODR violations somehow?
if (Record[Idx++]) {
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ CD->NumCtorInitializers = Record[Idx++];
+ if (CD->NumCtorInitializers)
+ CD->CtorInitializers =
+ Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
+ }
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
}
@@ -440,24 +529,28 @@ void ASTDeclReader::VisitDecl(Decl *D) {
D->FromASTFile = true;
D->setModulePrivate(Record[Idx++]);
D->Hidden = D->isModulePrivate();
-
+
// Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible.
if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
// Store the owning submodule ID in the declaration.
D->setOwningModuleID(SubmoduleID);
-
- // Module-private declarations are never visible, so there is no work to do.
- if (!D->isModulePrivate()) {
- if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
- if (Owner->NameVisibility != Module::AllVisible) {
- // The owning module is not visible. Mark this declaration as hidden.
- D->Hidden = true;
-
- // Note that this declaration was hidden because its owning module is
- // not yet visible.
- Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D);
- }
+
+ if (D->Hidden) {
+ // Module-private declarations are never visible, so there is no work to do.
+ } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ // If local visibility is being tracked, this declaration will become
+ // hidden and visible as the owning module does. Inform Sema that this
+ // declaration might not be visible.
+ D->Hidden = true;
+ } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
+ if (Owner->NameVisibility != Module::AllVisible) {
+ // The owning module is not visible. Mark this declaration as hidden.
+ D->Hidden = true;
+
+ // Note that this declaration was hidden because its owning module is
+ // not yet visible.
+ Reader.HiddenNamesMap[Owner].push_back(D);
}
}
}
@@ -470,8 +563,7 @@ void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
VisitDecl(ND);
ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
- if (needsAnonymousDeclarationNumber(ND))
- AnonymousDeclNumber = Record[Idx++];
+ AnonymousDeclNumber = Record[Idx++];
}
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
@@ -564,9 +656,21 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
if (ED->IsCompleteDefinition &&
Reader.getContext().getLangOpts().Modules &&
Reader.getContext().getLangOpts().CPlusPlus) {
- if (EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()]) {
+ EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
+ if (!OldDef) {
+ // This is the first time we've seen an imported definition. Look for a
+ // local definition before deciding that we are the first definition.
+ for (auto *D : merged_redecls(ED->getCanonicalDecl())) {
+ if (!D->isFromASTFile() && D->isCompleteDefinition()) {
+ OldDef = D;
+ break;
+ }
+ }
+ }
+ if (OldDef) {
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
ED->IsCompleteDefinition = false;
+ mergeDefinitionVisibility(OldDef, ED);
} else {
OldDef = ED;
}
@@ -714,14 +818,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C);
void *InsertPos = nullptr;
FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
- CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
+ FunctionTemplateSpecializationInfo *ExistingInfo =
+ CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
if (InsertPos)
CommonPtr->Specializations.InsertNode(FTInfo, InsertPos);
else {
assert(Reader.getContext().getLangOpts().Modules &&
"already deserialized this template specialization");
- // FIXME: This specialization is a redeclaration of one from another
- // module. Merge it.
+ mergeRedeclarable(FD, ExistingInfo->Function, Redecl);
}
}
break;
@@ -743,8 +847,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setDependentTemplateSpecialization(Reader.getContext(),
TemplDecls, TemplArgs);
-
- // FIXME: Merging.
+ // These are not merged; we don't need to merge redeclarations of dependent
+ // template friends.
break;
}
}
@@ -803,18 +907,49 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
}
+void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ VisitTypedefNameDecl(D);
+ D->Variance = Record[Idx++];
+ D->Index = Record[Idx++];
+ D->VarianceLoc = ReadSourceLocation(Record, Idx);
+ D->ColonLoc = ReadSourceLocation(Record, Idx);
+}
+
void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
VisitNamedDecl(CD);
CD->setAtStartLoc(ReadSourceLocation(Record, Idx));
CD->setAtEndRange(ReadSourceRange(Record, Idx));
}
+ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
+ unsigned numParams = Record[Idx++];
+ if (numParams == 0)
+ return nullptr;
+
+ SmallVector<ObjCTypeParamDecl *, 4> typeParams;
+ typeParams.reserve(numParams);
+ for (unsigned i = 0; i != numParams; ++i) {
+ auto typeParam = ReadDeclAs<ObjCTypeParamDecl>(Record, Idx);
+ if (!typeParam)
+ return nullptr;
+
+ typeParams.push_back(typeParam);
+ }
+
+ SourceLocation lAngleLoc = ReadSourceLocation(Record, Idx);
+ SourceLocation rAngleLoc = ReadSourceLocation(Record, Idx);
+
+ return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc,
+ typeParams, rAngleLoc);
+}
+
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
RedeclarableResult Redecl = VisitRedeclarable(ID);
VisitObjCContainerDecl(ID);
TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
mergeRedeclarable(ID, Redecl);
-
+
+ ID->TypeParamList = ReadObjCTypeParamList();
if (Record[Idx++]) {
// Read the definition.
ID->allocateDefinitionData();
@@ -826,8 +961,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
ObjCInterfaceDecl::DefinitionData &Data = ID->data();
// Read the superclass.
- Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
- Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
+ Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx);
Data.EndLoc = ReadSourceLocation(Record, Idx);
Data.HasDesignatedInitializers = Record[Idx++];
@@ -924,6 +1058,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
Reader.CategoriesDeserialized.insert(CD);
CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+ CD->TypeParamList = ReadObjCTypeParamList();
unsigned NumProtoRefs = Record[Idx++];
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
ProtoRefs.reserve(NumProtoRefs);
@@ -946,13 +1081,13 @@ void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
D->setAtLoc(ReadSourceLocation(Record, Idx));
D->setLParenLoc(ReadSourceLocation(Record, Idx));
- D->setType(GetTypeSourceInfo(Record, Idx));
- // FIXME: stable encoding
+ QualType T = Reader.readType(F, Record, Idx);
+ TypeSourceInfo *TSI = GetTypeSourceInfo(Record, Idx);
+ D->setType(T, TSI);
D->setPropertyAttributes(
(ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
D->setPropertyAttributesAsWritten(
(ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
- // FIXME: stable encoding
D->setPropertyImplementation(
(ObjCPropertyDecl::PropertyControl)Record[Idx++]);
D->setGetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector());
@@ -981,8 +1116,9 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
D->setHasNonZeroConstructors(Record[Idx++]);
D->setHasDestructors(Record[Idx++]);
- std::tie(D->IvarInitializers, D->NumIvarInitializers) =
- Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ D->NumIvarInitializers = Record[Idx++];
+ if (D->NumIvarInitializers)
+ D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
}
@@ -1041,13 +1177,15 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
VD->VarDeclBits.TSCSpec = Record[Idx++];
VD->VarDeclBits.InitStyle = Record[Idx++];
- VD->VarDeclBits.ExceptionVar = Record[Idx++];
- VD->VarDeclBits.NRVOVariable = Record[Idx++];
- VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
- VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
- VD->VarDeclBits.IsConstexpr = Record[Idx++];
- VD->VarDeclBits.IsInitCapture = Record[Idx++];
- VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
+ if (!isa<ParmVarDecl>(VD)) {
+ VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++];
+ VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++];
+ VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++];
+ VD->NonParmVarDeclBits.ARCPseudoStrong = Record[Idx++];
+ VD->NonParmVarDeclBits.IsConstexpr = Record[Idx++];
+ VD->NonParmVarDeclBits.IsInitCapture = Record[Idx++];
+ VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
+ }
Linkage VarLinkage = Linkage(Record[Idx++]);
VD->setCachedLinkage(VarLinkage);
@@ -1189,13 +1327,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
+ // Defer loading the anonymous namespace until we've finished merging
+ // this namespace; loading it might load a later declaration of the
+ // same namespace, and we have an invariant that older declarations
+ // get merged before newer ones try to merge.
+ GlobalDeclID AnonNamespace = 0;
if (Redecl.getFirstID() == ThisDeclID) {
- // Each module has its own anonymous namespace, which is disjoint from
- // any other module's anonymous namespaces, so don't attach the anonymous
- // namespace at all.
- NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
- if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
- D->setAnonymousNamespace(Anon);
+ AnonNamespace = ReadDeclID(Record, Idx);
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
@@ -1203,6 +1341,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
}
mergeRedeclarable(D, Redecl);
+
+ if (AnonNamespace) {
+ // Each module has its own anonymous namespace, which is disjoint from
+ // any other module's anonymous namespaces, so don't attach the anonymous
+ // namespace at all.
+ NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
+ if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
+ D->setAnonymousNamespace(Anon);
+ }
}
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
@@ -1353,25 +1500,46 @@ void ASTDeclReader::ReadCXXDefinitionData(
}
void ASTDeclReader::MergeDefinitionData(
- CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) {
+ CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) {
assert(D->DefinitionData.getNotUpdated() &&
"merging class definition into non-definition");
auto &DD = *D->DefinitionData.getNotUpdated();
- // If the new definition has new special members, let the name lookup
- // code know that it needs to look in the new definition too.
- //
- // FIXME: We only need to do this if the merged definition declares members
- // that this definition did not declare, or if it defines members that this
- // definition did not define.
- if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) {
+ if (DD.Definition != MergeDD.Definition) {
+ // If the new definition has new special members, let the name lookup
+ // code know that it needs to look in the new definition too.
+ //
+ // FIXME: We only need to do this if the merged definition declares members
+ // that this definition did not declare, or if it defines members that this
+ // definition did not define.
Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
DD.Definition->setHasExternalVisibleStorage();
+
+ // Track that we merged the definitions.
+ Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
+ DD.Definition));
+ Reader.PendingDefinitions.erase(MergeDD.Definition);
+ MergeDD.Definition->IsCompleteDefinition = false;
+ mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
+ }
+
+ auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
+ if (PFDI != Reader.PendingFakeDefinitionData.end() &&
+ PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) {
+ // We faked up this definition data because we found a class for which we'd
+ // not yet loaded the definition. Replace it with the real thing now.
+ assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?");
+ PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded;
+
+ // Don't change which declaration is the definition; that is required
+ // to be invariant once we select it.
+ auto *Def = DD.Definition;
+ DD = std::move(MergeDD);
+ DD.Definition = Def;
+ return;
}
// FIXME: Move this out into a .def file?
- // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than
- // asserting; this can happen in the case of an ODR violation.
bool DetectedOdrViolation = false;
#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
#define MATCH_FIELD(Field) \
@@ -1442,7 +1610,7 @@ void ASTDeclReader::MergeDefinitionData(
Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
}
-void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
+void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
struct CXXRecordDecl::DefinitionData *DD;
ASTContext &C = Reader.getContext();
@@ -1457,36 +1625,25 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
ReadCXXDefinitionData(*DD, Record, Idx);
- // If we're reading an update record, we might already have a definition for
- // this record. If so, just merge into it.
- if (D->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(D, *DD);
+ // We might already have a definition for this record. This can happen either
+ // because we're reading an update record, or because we've already done some
+ // merging. Either way, just merge into it.
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ if (Canon->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(Canon, std::move(*DD));
+ D->DefinitionData = Canon->DefinitionData;
return;
}
- // Propagate the DefinitionData pointer to the canonical declaration, so
- // that all other deserialized declarations will see it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
- if (Canon == D) {
- D->DefinitionData = DD;
- D->IsCompleteDefinition = true;
- } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
- // We have already deserialized a definition of this record. This
- // definition is no longer really a definition. Note that the pre-existing
- // definition is the *real* definition.
- Reader.MergedDeclContexts.insert(
- std::make_pair(D, CanonDD->Definition));
- D->DefinitionData = Canon->DefinitionData;
- D->IsCompleteDefinition = false;
- MergeDefinitionData(D, *DD);
- } else {
- Canon->DefinitionData = DD;
- D->DefinitionData = Canon->DefinitionData;
- D->IsCompleteDefinition = true;
+ // Mark this declaration as being a definition.
+ D->IsCompleteDefinition = true;
+ D->DefinitionData = DD;
- // Note that we have deserialized a definition. Any declarations
- // deserialized before this one will be be given the DefinitionData
- // pointer at the end.
+ // If this is not the first declaration or is an update record, we can have
+ // other redeclarations already. Make a note that we need to propagate the
+ // DefinitionData pointer onto them.
+ if (Update || Canon != D) {
+ Canon->DefinitionData = D->DefinitionData;
Reader.PendingDefinitions.insert(D);
}
}
@@ -1535,7 +1692,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
bool WasDefinition = Record[Idx++];
if (WasDefinition)
- ReadCXXRecordDefinition(D);
+ ReadCXXRecordDefinition(D, /*Update*/false);
else
// Propagate DefinitionData pointer from the canonical declaration.
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
@@ -1576,17 +1733,20 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
- D->setInheritedConstructor(CD);
+ if (D->isCanonicalDecl())
+ D->setInheritedConstructor(CD->getCanonicalDecl());
D->IsExplicitSpecified = Record[Idx++];
- // FIXME: We should defer loading this until we need the constructor's body.
- std::tie(D->CtorInitializers, D->NumCtorInitializers) =
- Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx);
+ if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) {
+ auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!Canon->OperatorDelete)
+ Canon->OperatorDelete = OperatorDelete;
+ }
}
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
@@ -1645,9 +1805,6 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
= Reader.ReadTemplateParameterList(F, Record, Idx);
D->init(TemplatedDecl, TemplateParams);
- // FIXME: If this is a redeclaration of a template from another module, handle
- // inheritance of default template arguments.
-
return PatternID;
}
@@ -1690,36 +1847,34 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
return Redecl;
}
+static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
+ SmallVectorImpl<DeclID> &IDs) {
+ assert(!IDs.empty() && "no IDs to add to list");
+ if (Old) {
+ IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+ std::sort(IDs.begin(), IDs.end());
+ IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
+ }
+
+ auto *Result = new (Context) DeclID[1 + IDs.size()];
+ *Result = IDs.size();
+ std::copy(IDs.begin(), IDs.end(), Result + 1);
+ return Result;
+}
+
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (ThisDeclID == Redecl.getFirstID()) {
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 2> SpecIDs;
- SpecIDs.push_back(0);
-
- // Specializations.
- unsigned Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- // Partial specializations.
- Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- if (SpecIDs[0]) {
- typedef serialization::DeclID DeclID;
-
- // FIXME: Append specializations!
- CommonPtr->LazySpecializations
- = new (Reader.getContext()) DeclID [SpecIDs.size()];
- memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
- SpecIDs.size() * sizeof(DeclID));
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
+
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
@@ -1741,30 +1896,13 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
if (ThisDeclID == Redecl.getFirstID()) {
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 2> SpecIDs;
- SpecIDs.push_back(0);
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
- // Specializations.
- unsigned Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- // Partial specializations.
- Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- if (SpecIDs[0]) {
- typedef serialization::DeclID DeclID;
-
- // FIXME: Append specializations!
- CommonPtr->LazySpecializations =
- new (Reader.getContext()) DeclID[SpecIDs.size()];
- memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
- SpecIDs.size() * sizeof(DeclID));
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
}
@@ -1822,15 +1960,10 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
// This declaration might be a definition. Merge with any existing
// definition.
if (auto *DDD = D->DefinitionData.getNotUpdated()) {
- if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(CanonSpec, *DDD);
- Reader.PendingDefinitions.erase(D);
- Reader.MergedDeclContexts.insert(
- std::make_pair(D, CanonDD->Definition));
- D->IsCompleteDefinition = false;
- } else {
+ if (CanonSpec->DefinitionData.getNotUpdated())
+ MergeDefinitionData(CanonSpec, std::move(*DDD));
+ else
CanonSpec->DefinitionData = D->DefinitionData;
- }
}
D->DefinitionData = CanonSpec->DefinitionData;
}
@@ -1876,17 +2009,13 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (ThisDeclID == Redecl.getFirstID()) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
- // Read the function specialization declaration IDs. The specializations
- // themselves will be loaded if they're needed.
- if (unsigned NumSpecs = Record[Idx++]) {
- // FIXME: Append specializations!
- FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- CommonPtr->LazySpecializations = new (Reader.getContext())
- serialization::DeclID[NumSpecs + 1];
- CommonPtr->LazySpecializations[0] = NumSpecs;
- for (unsigned I = 0; I != NumSpecs; ++I)
- CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx);
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
}
@@ -1979,9 +2108,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
D->setDeclaredWithTypename(Record[Idx++]);
- bool Inherited = Record[Idx++];
- TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx);
- D->setDefaultArgument(DefArg, Inherited);
+ if (Record[Idx++])
+ D->setDefaultArgument(GetTypeSourceInfo(Record, Idx));
}
void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
@@ -1998,11 +2126,8 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
} else {
// Rest of NonTypeTemplateParmDecl.
D->ParameterPack = Record[Idx++];
- if (Record[Idx++]) {
- Expr *DefArg = Reader.ReadExpr(F);
- bool Inherited = Record[Idx++];
- D->setDefaultArgument(DefArg, Inherited);
- }
+ if (Record[Idx++])
+ D->setDefaultArgument(Reader.ReadExpr(F));
}
}
@@ -2018,10 +2143,10 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
Data[I] = Reader.ReadTemplateParameterList(F, Record, Idx);
} else {
// Rest of TemplateTemplateParmDecl.
- TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(F, Record, Idx);
- bool IsInherited = Record[Idx++];
- D->setDefaultArgument(Arg, IsInherited);
D->ParameterPack = Record[Idx++];
+ if (Record[Idx++])
+ D->setDefaultArgument(Reader.getContext(),
+ Reader.ReadTemplateArgumentLoc(F, Record, Idx));
}
}
@@ -2049,15 +2174,29 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
}
template <typename T>
-ASTDeclReader::RedeclarableResult
+ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
DeclID FirstDeclID = ReadDeclID(Record, Idx);
-
+ Decl *MergeWith = nullptr;
+ bool IsKeyDecl = ThisDeclID == FirstDeclID;
+
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
- if (FirstDeclID == 0)
+ if (FirstDeclID == 0) {
FirstDeclID = ThisDeclID;
-
+ IsKeyDecl = true;
+ } else if (unsigned N = Record[Idx++]) {
+ IsKeyDecl = false;
+
+ // We have some declarations that must be before us in our redeclaration
+ // chain. Read them now, and remember that we ought to merge with one of
+ // them.
+ // FIXME: Provide a known merge target to the second and subsequent such
+ // declaration.
+ for (unsigned I = 0; I != N; ++I)
+ MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+ }
+
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
if (FirstDecl != D) {
// We delay loading of the redeclaration chain to avoid deeply nested calls.
@@ -2065,6 +2204,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// which is the one that matters and mark the real previous DeclID to be
// loaded & attached later on.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
+ D->First = FirstDecl->getCanonicalDecl();
}
// Note that this declaration has been deserialized.
@@ -2072,8 +2212,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// The result structure takes care to note that we need to load the
// other declaration chains for this ID.
- return RedeclarableResult(Reader, FirstDeclID,
- static_cast<T *>(D)->getKind());
+ return RedeclarableResult(Reader, FirstDeclID, MergeWith,
+ static_cast<T *>(D)->getKind(), IsKeyDecl);
}
/// \brief Attempts to merge the given declaration (D) with another declaration
@@ -2083,23 +2223,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
RedeclarableResult &Redecl,
DeclID TemplatePatternID) {
T *D = static_cast<T*>(DBase);
- T *DCanon = D->getCanonicalDecl();
- if (D != DCanon &&
- // IDs < NUM_PREDEF_DECL_IDS are not loaded from an AST file.
- Redecl.getFirstID() >= NUM_PREDEF_DECL_IDS &&
- (!Reader.getContext().getLangOpts().Modules ||
- Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) {
- // All redeclarations between this declaration and its originally-canonical
- // declaration get pulled in when we load DCanon; we don't need to
- // perform any more merging now.
- Redecl.suppress();
- }
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
- if (FindExistingResult ExistingRes = findExisting(D))
+ // If we're not the canonical declaration, we don't need to merge.
+ if (!DBase->isFirstDecl())
+ return;
+
+ if (auto *Existing = Redecl.getKnownMergeTarget())
+ // We already know of an existing declaration we should merge with.
+ mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
+ else if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes)
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
}
@@ -2116,25 +2252,26 @@ template<typename T> static T assert_cast(...) {
/// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID) {
+ DeclID DsID, bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
- DPattern->getKind());
+ /*MergeWith*/ExistingPattern, DPattern->getKind(),
+ IsKeyDecl);
+
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
// FIXME: This is duplicated in several places. Refactor.
auto *ExistingClass =
cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
- if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(ExistingClass, *DDD);
- Reader.PendingDefinitions.erase(DClass);
- Reader.MergedDeclContexts.insert(
- std::make_pair(DClass, ExistingDD->Definition));
- DClass->IsCompleteDefinition = false;
+ if (ExistingClass->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(ExistingClass, std::move(*DDD));
} else {
ExistingClass->DefinitionData = DClass->DefinitionData;
+ // We may have skipped this before because we thought that DClass
+ // was the canonical declaration.
+ Reader.PendingDefinitions.insert(DClass);
}
}
DClass->DefinitionData = ExistingClass->DefinitionData;
@@ -2163,14 +2300,18 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
- assert(DCanon->getGlobalID() == Redecl.getFirstID());
+ assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
+ "already merged this declaration");
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
+ D->First = ExistingCanon;
// When we merge a namespace, update its pointer to the first namespace.
+ // We cannot have loaded any redeclarations of this declaration yet, so
+ // there's nothing else that needs to be updated.
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
assert_cast<NamespaceDecl*>(ExistingCanon));
@@ -2179,16 +2320,13 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
mergeTemplatePattern(
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
- TemplatePatternID);
+ TemplatePatternID, Redecl.isKeyDecl());
- // If this declaration was the canonical declaration, make a note of
- // that. We accept the linear algorithm here because the number of
- // unique canonical declarations of an entity should always be tiny.
- if (DCanon == D) {
- SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
- if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
- == Merged.end())
- Merged.push_back(Redecl.getFirstID());
+ // If this declaration is a key declaration, make a note of that.
+ if (Redecl.isKeyDecl()) {
+ Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID());
+ if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
+ Reader.PendingDeclChains.push_back(ExistingCanon);
}
}
}
@@ -2523,48 +2661,76 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return NAX->getNamespace()->Equals(NAY->getNamespace());
}
- // FIXME: Many other cases to implement.
return false;
}
/// Find the context in which we should search for previous declarations when
/// looking for declarations to merge.
-static DeclContext *getPrimaryContextForMerging(DeclContext *DC) {
+DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
+ DeclContext *DC) {
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
return ND->getOriginalNamespace();
- // There is one tricky case here: if DC is a class with no definition, then
- // we're merging a declaration whose definition is added by an update record,
- // but we've not yet loaded that update record. In this case, we use the
- // canonical declaration for merging until we get a real definition.
- // FIXME: When we add a definition, we may need to move the partial lookup
- // information from the canonical declaration onto the chosen definition.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
- return RD->getPrimaryContext();
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ // Try to dig out the definition.
+ auto *DD = RD->DefinitionData.getNotUpdated();
+ if (!DD)
+ DD = RD->getCanonicalDecl()->DefinitionData.getNotUpdated();
+
+ // If there's no definition yet, then DC's definition is added by an update
+ // record, but we've not yet loaded that update record. In this case, we
+ // commit to DC being the canonical definition now, and will fix this when
+ // we load the update record.
+ if (!DD) {
+ DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD);
+ RD->IsCompleteDefinition = true;
+ RD->DefinitionData = DD;
+ RD->getCanonicalDecl()->DefinitionData = DD;
+
+ // Track that we did this horrible thing so that we can fix it later.
+ Reader.PendingFakeDefinitionData.insert(
+ std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
+ }
+
+ return DD->Definition;
+ }
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
: nullptr;
+ // We can see the TU here only if we have no Sema object. In that case,
+ // there's no TU scope to look in, so using the DC alone is sufficient.
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
+ return TU;
+
return nullptr;
}
ASTDeclReader::FindExistingResult::~FindExistingResult() {
+ // Record that we had a typedef name for linkage whether or not we merge
+ // with that declaration.
+ if (TypedefNameForLinkage) {
+ DeclContext *DC = New->getDeclContext()->getRedeclContext();
+ Reader.ImportedTypedefNamesForLinkage.insert(
+ std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
+ return;
+ }
+
if (!AddResult || Existing)
return;
DeclarationName Name = New->getDeclName();
DeclContext *DC = New->getDeclContext()->getRedeclContext();
- if (TypedefNameForLinkage) {
- Reader.ImportedTypedefNamesForLinkage.insert(
- std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
- } else if (!Name) {
- assert(needsAnonymousDeclarationNumber(New));
+ if (needsAnonymousDeclarationNumber(New)) {
setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
AnonymousDeclNumber, New);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
- Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name);
- } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
+ if (Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name))
+ Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()]
+ .push_back(New);
+ } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
// Add the declaration to its redeclaration context so later merging
// lookups will find it.
MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true);
@@ -2582,12 +2748,11 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
// If we found a typedef declaration that gives a name to some other
// declaration, then we want that inner declaration. Declarations from
// AST files are handled via ImportedTypedefNamesForLinkage.
- if (Found->isFromASTFile()) return 0;
- if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) {
- if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>())
- if (TT->getDecl()->getTypedefNameForAnonDecl() == TND)
- return TT->getDecl();
- }
+ if (Found->isFromASTFile())
+ return 0;
+
+ if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
+ return TND->getAnonDeclWithTypedefName();
return 0;
}
@@ -2608,17 +2773,12 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
// If this is the first time, but we have parsed a declaration of the context,
// build the anonymous declaration list from the parsed declaration.
if (!cast<Decl>(DC)->isFromASTFile()) {
- unsigned Index = 0;
- for (Decl *LexicalD : DC->decls()) {
- auto *ND = dyn_cast<NamedDecl>(LexicalD);
- if (!ND || !needsAnonymousDeclarationNumber(ND))
- continue;
- if (Previous.size() == Index)
+ numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) {
+ if (Previous.size() == Number)
Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
else
- Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl());
- ++Index;
- }
+ Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl());
+ });
}
return Index < Previous.size() ? Previous[Index] : nullptr;
@@ -2646,15 +2806,10 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// unmergeable contexts.
FindExistingResult Result(Reader, D, /*Existing=*/nullptr,
AnonymousDeclNumber, TypedefNameForLinkage);
- // FIXME: We may still need to pull in the redeclaration chain; there can
- // be redeclarations via 'decltype'.
Result.suppress();
return Result;
}
- // FIXME: Bail out for non-canonical declarations. We will have performed any
- // necessary merging already.
-
DeclContext *DC = D->getDeclContext()->getRedeclContext();
if (TypedefNameForLinkage) {
auto It = Reader.ImportedTypedefNamesForLinkage.find(
@@ -2667,16 +2822,16 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// was not imported.
}
- if (!Name) {
+ if (needsAnonymousDeclarationNumber(D)) {
// This is an anonymous declaration that we may need to merge. Look it up
// in its context by number.
- assert(needsAnonymousDeclarationNumber(D));
if (auto *Existing = getAnonymousDeclForMerging(
Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
if (isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
// Temporarily consider the identifier to be up-to-date. We don't want to
@@ -2710,7 +2865,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
}
- } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
+ } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
@@ -2738,20 +2893,47 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
}
template<typename DeclT>
+Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) {
+ return D->RedeclLink.getLatestNotUpdated();
+}
+Decl *ASTDeclReader::getMostRecentDeclImpl(...) {
+ llvm_unreachable("getMostRecentDecl on non-redeclarable declaration");
+}
+
+Decl *ASTDeclReader::getMostRecentDecl(Decl *D) {
+ assert(D);
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ return getMostRecentDeclImpl(cast<TYPE##Decl>(D));
+#include "clang/AST/DeclNodes.inc"
+ }
+ llvm_unreachable("unknown decl kind");
+}
+
+Decl *ASTReader::getMostRecentExistingDecl(Decl *D) {
+ return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl());
+}
+
+template<typename DeclT>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<DeclT> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
+ D->First = cast<DeclT>(Previous)->First;
}
namespace clang {
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
FunctionDecl *FD = static_cast<FunctionDecl*>(D);
FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
FD->RedeclLink.setPrevious(PrevFD);
+ FD->First = PrevFD->First;
// If the previous declaration is an inline function declaration, then this
// declaration is too.
@@ -2774,16 +2956,17 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
FD->IsInline = true;
}
- // If this declaration has an unresolved exception specification but the
- // previous declaration had a resolved one, resolve the exception
- // specification now.
+ // If we need to propagate an exception specification along the redecl
+ // chain, make a note of that so that we can do so later.
auto *FPT = FD->getType()->getAs<FunctionProtoType>();
auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
- if (FPT && PrevFPT &&
- isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
- !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) {
- Reader.Context.adjustExceptionSpec(
- FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
+ if (FPT && PrevFPT) {
+ bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
+ bool WasUnresolved =
+ isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
+ if (IsUnresolved != WasUnresolved)
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
}
}
}
@@ -2791,15 +2974,52 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
}
+/// Inherit the default template argument from \p From to \p To. Returns
+/// \c false if there is no default template for \p From.
+template <typename ParmDecl>
+static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From,
+ Decl *ToD) {
+ auto *To = cast<ParmDecl>(ToD);
+ if (!From->hasDefaultArgument())
+ return false;
+ To->setInheritedDefaultArgument(Context, From);
+ return true;
+}
+
+static void inheritDefaultTemplateArguments(ASTContext &Context,
+ TemplateDecl *From,
+ TemplateDecl *To) {
+ auto *FromTP = From->getTemplateParameters();
+ auto *ToTP = To->getTemplateParameters();
+ assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
+
+ for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
+ NamedDecl *FromParam = FromTP->getParam(N - I - 1);
+ NamedDecl *ToParam = ToTP->getParam(N - I - 1);
+
+ if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
+ if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam))
+ break;
+ } else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
+ if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
+ break;
+ } else {
+ if (!inheritDefaultTemplateArgument(
+ Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
+ break;
+ }
+ }
+}
+
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
assert(D && Previous);
switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
-#define DECL(TYPE, BASE) \
- case Decl::TYPE: \
- attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \
break;
#include "clang/AST/DeclNodes.inc"
}
@@ -2817,6 +3037,12 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
// be too.
if (Previous->Used)
D->Used = true;
+
+ // If the declaration declares a template, it may inherit default arguments
+ // from the previous declaration.
+ if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ inheritDefaultTemplateArguments(Reader.getContext(),
+ cast<TemplateDecl>(Previous), TD);
}
template<typename DeclT>
@@ -2859,29 +3085,6 @@ void ASTReader::markIncompleteDeclChain(Decl *D) {
}
}
-ASTReader::MergedDeclsMap::iterator
-ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
- // If we don't have any stored merged declarations, just look in the
- // merged declarations set.
- StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
- if (StoredPos == StoredMergedDecls.end())
- return MergedDecls.find(Canon);
-
- // Append the stored merged declarations to the merged declarations set.
- MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
- if (Pos == MergedDecls.end())
- Pos = MergedDecls.insert(std::make_pair(Canon,
- SmallVector<DeclID, 2>())).first;
- Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
- StoredMergedDecls.erase(StoredPos);
-
- // Sort and uniquify the set of merged declarations.
- llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
- Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
- Pos->second.end());
- return Pos;
-}
-
/// \brief Read the declaration at the given offset from the AST file.
Decl *ASTReader::ReadDeclRecord(DeclID ID) {
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
@@ -3086,6 +3289,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
return nullptr;
+ case DECL_CXX_CTOR_INITIALIZERS:
+ Error("attempt to read a C++ ctor initializer record as a declaration");
+ return nullptr;
case DECL_IMPORT:
// Note: last entry of the ImportDecl record is the number of stored source
// locations.
@@ -3097,6 +3303,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_EMPTY:
D = EmptyDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_OBJC_TYPE_PARAM:
+ D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
+ break;
}
assert(D && "Unknown declaration reading AST file");
@@ -3199,47 +3408,55 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
}
namespace {
- /// \brief Module visitor class that finds all of the redeclarations of a
- ///
+ /// \brief Module visitor class that finds all of the redeclarations of a
+ /// redeclarable declaration.
class RedeclChainVisitor {
ASTReader &Reader;
SmallVectorImpl<DeclID> &SearchDecls;
llvm::SmallPtrSetImpl<Decl *> &Deserialized;
GlobalDeclID CanonID;
SmallVector<Decl *, 4> Chain;
-
+
public:
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
llvm::SmallPtrSetImpl<Decl *> &Deserialized,
GlobalDeclID CanonID)
: Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
- CanonID(CanonID) {
- for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
- addToChain(Reader.GetDecl(SearchDecls[I]));
+ CanonID(CanonID) {
+ // Ensure that the canonical ID goes at the start of the chain.
+ addToChain(Reader.GetDecl(CanonID));
}
-
- static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
- if (Preorder)
- return false;
-
- return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
+
+ static ModuleManager::DFSPreorderControl
+ visitPreorder(ModuleFile &M, void *UserData) {
+ return static_cast<RedeclChainVisitor *>(UserData)->visitPreorder(M);
}
-
+
+ static bool visitPostorder(ModuleFile &M, void *UserData) {
+ return static_cast<RedeclChainVisitor *>(UserData)->visitPostorder(M);
+ }
+
void addToChain(Decl *D) {
if (!D)
return;
-
+
if (Deserialized.erase(D))
Chain.push_back(D);
}
-
+
void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
// Map global ID of the first declaration down to the local ID
// used in this module file.
DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
if (!ID)
return;
-
+
+ // If the search decl was from this module, add it to the chain before any
+ // of its redeclarations in this module or users of it, and after any from
+ // imported modules.
+ if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M))
+ addToChain(Reader.GetDecl(GlobalID));
+
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
const LocalRedeclarationsInfo Compare = { ID, 0 };
@@ -3248,20 +3465,9 @@ namespace {
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
Compare);
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
- Result->FirstID != ID) {
- // If we have a previously-canonical singleton declaration that was
- // merged into another redeclaration chain, create a trivial chain
- // for this single declaration so that it will get wired into the
- // complete redeclaration chain.
- if (GlobalID != CanonID &&
- GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
- GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) {
- addToChain(Reader.GetDecl(GlobalID));
- }
-
+ Result->FirstID != ID)
return;
- }
-
+
// Dig out all of the redeclarations.
unsigned Offset = Result->Offset;
unsigned N = M.RedeclarationChains[Offset];
@@ -3269,13 +3475,39 @@ namespace {
for (unsigned I = 0; I != N; ++I)
addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++]));
}
-
- bool visit(ModuleFile &M) {
+
+ bool needsToVisitImports(ModuleFile &M, GlobalDeclID GlobalID) {
+ DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
+ if (!ID)
+ return false;
+
+ const LocalRedeclarationsInfo Compare = {ID, 0};
+ const LocalRedeclarationsInfo *Result = std::lower_bound(
+ M.RedeclarationsMap,
+ M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
+ if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
+ Result->FirstID != ID) {
+ return true;
+ }
+ unsigned Offset = Result->Offset;
+ unsigned N = M.RedeclarationChains[Offset];
+ // We don't need to visit a module or any of its imports if we've already
+ // deserialized the redecls from this module.
+ return N != 0;
+ }
+
+ ModuleManager::DFSPreorderControl visitPreorder(ModuleFile &M) {
+ for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) {
+ if (needsToVisitImports(M, SearchDecls[I]))
+ return ModuleManager::Continue;
+ }
+ return ModuleManager::SkipImports;
+ }
+
+ bool visitPostorder(ModuleFile &M) {
// Visit each of the declarations.
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
searchForID(M, SearchDecls[I]);
- // FIXME: If none of the SearchDecls had local IDs in this module, can
- // we avoid searching any ancestor module files?
return false;
}
@@ -3285,41 +3517,46 @@ namespace {
};
}
-void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
- Decl *D = GetDecl(ID);
- Decl *CanonDecl = D->getCanonicalDecl();
-
+void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
+ // The decl might have been merged into something else after being added to
+ // our list. If it was, just skip it.
+ if (!CanonDecl->isCanonicalDecl())
+ return;
+
// Determine the set of declaration IDs we'll be searching for.
- SmallVector<DeclID, 1> SearchDecls;
- GlobalDeclID CanonID = 0;
- if (D == CanonDecl) {
- SearchDecls.push_back(ID); // Always first.
- CanonID = ID;
- }
- MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
- if (MergedPos != MergedDecls.end())
- SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());
-
+ SmallVector<DeclID, 16> SearchDecls;
+ GlobalDeclID CanonID = CanonDecl->getGlobalID();
+ if (CanonID)
+ SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first.
+ KeyDeclsMap::iterator KeyPos = KeyDecls.find(CanonDecl);
+ if (KeyPos != KeyDecls.end())
+ SearchDecls.append(KeyPos->second.begin(), KeyPos->second.end());
+
// Build up the list of redeclarations.
RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
- ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor);
-
+ ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visitPreorder,
+ &RedeclChainVisitor::visitPostorder, &Visitor);
+
// Retrieve the chains.
ArrayRef<Decl *> Chain = Visitor.getChain();
- if (Chain.empty())
+ if (Chain.empty() || (Chain.size() == 1 && Chain[0] == CanonDecl))
return;
-
+
// Hook up the chains.
- Decl *MostRecent = CanonDecl->getMostRecentDecl();
+ //
+ // FIXME: We have three different dispatches on decl kind here; maybe
+ // we should instead generate one loop per kind and dispatch up-front?
+ Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
+ if (!MostRecent)
+ MostRecent = CanonDecl;
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
if (Chain[I] == CanonDecl)
continue;
- ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent);
+ ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl);
MostRecent = Chain[I];
}
-
- ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
+ ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
}
namespace {
@@ -3445,48 +3682,6 @@ void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor);
}
-namespace {
-/// Iterator over the redeclarations of a declaration that have already
-/// been merged into the same redeclaration chain.
-template<typename DeclT>
-class MergedRedeclIterator {
- DeclT *Start, *Canonical, *Current;
-public:
- MergedRedeclIterator() : Current(nullptr) {}
- MergedRedeclIterator(DeclT *Start)
- : Start(Start), Canonical(nullptr), Current(Start) {}
-
- DeclT *operator*() { return Current; }
-
- MergedRedeclIterator &operator++() {
- if (Current->isFirstDecl()) {
- Canonical = Current;
- Current = Current->getMostRecentDecl();
- } else
- Current = Current->getPreviousDecl();
-
- // If we started in the merged portion, we'll reach our start position
- // eventually. Otherwise, we'll never reach it, but the second declaration
- // we reached was the canonical declaration, so stop when we see that one
- // again.
- if (Current == Start || Current == Canonical)
- Current = nullptr;
- return *this;
- }
-
- friend bool operator!=(const MergedRedeclIterator &A,
- const MergedRedeclIterator &B) {
- return A.Current != B.Current;
- }
-};
-}
-template<typename DeclT>
-llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
- return llvm::iterator_range<MergedRedeclIterator<DeclT>>(
- MergedRedeclIterator<DeclT>(D),
- MergedRedeclIterator<DeclT>());
-}
-
template<typename DeclT, typename Fn>
static void forAllLaterRedecls(DeclT *D, Fn F) {
F(D);
@@ -3513,13 +3708,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
while (Idx < Record.size()) {
switch ((DeclUpdateKind)Record[Idx++]) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+ auto *RD = cast<CXXRecordDecl>(D);
// FIXME: If we also have an update record for instantiating the
// definition of D, we need that to happen before we get here.
Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
assert(MD && "couldn't read decl from update record");
// FIXME: We should call addHiddenDecl instead, to add the member
// to its DeclContext.
- cast<CXXRecordDecl>(D)->addedMember(MD);
+ RD->addedMember(MD);
+
+ // If we've added a new special member to a class definition that is not
+ // the canonical definition, then we need special member lookups in the
+ // canonical definition to also look into our class.
+ auto *DD = RD->DefinitionData.getNotUpdated();
+ if (DD && DD->Definition != RD) {
+ auto &Merged = Reader.MergedLookups[DD->Definition];
+ // FIXME: Avoid the linear-time scan here.
+ if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end())
+ Merged.push_back(RD);
+ }
break;
}
@@ -3567,13 +3774,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
});
}
FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
- if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
- std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
- Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
- if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
- // FIXME: Check consistency.
- DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile,
- Record, Idx));
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ CD->NumCtorInitializers = Record[Idx++];
+ if (CD->NumCtorInitializers)
+ CD->CtorInitializers =
+ Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
+ }
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
@@ -3583,16 +3789,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
- bool HadDefinition = RD->getDefinition();
- ReadCXXRecordDefinition(RD);
+ auto *OldDD = RD->DefinitionData.getNotUpdated();
+ bool HadRealDefinition =
+ OldDD && (OldDD->Definition != RD ||
+ !Reader.PendingFakeDefinitionData.count(OldDD));
+ ReadCXXRecordDefinition(RD, /*Update*/true);
+
// Visible update is handled separately.
uint64_t LexicalOffset = Record[Idx++];
- if (!HadDefinition && LexicalOffset) {
+ if (!HadRealDefinition && LexicalOffset) {
RD->setHasExternalLexicalStorage(true);
Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
- std::make_pair(LexicalOffset, 0),
- ModuleFile.DeclContextInfos[RD]);
- Reader.PendingDefinitions.insert(RD);
+ std::make_pair(LexicalOffset, 0),
+ ModuleFile.DeclContextInfos[RD]);
+ Reader.PendingFakeDefinitionData.erase(OldDD);
}
auto TSK = (TemplateSpecializationKind)Record[Idx++];
@@ -3636,24 +3846,36 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
break;
}
+ case UPD_CXX_RESOLVED_DTOR_DELETE: {
+ // Set the 'operator delete' directly to avoid emitting another update
+ // record.
+ auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!First->OperatorDelete)
+ First->OperatorDelete = Del;
+ break;
+ }
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
- // FIXME: This doesn't send the right notifications if there are
- // ASTMutationListeners other than an ASTWriter.
FunctionProtoType::ExceptionSpecInfo ESI;
SmallVector<QualType, 8> ExceptionStorage;
Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
- for (auto *Redecl : merged_redecls(D)) {
- auto *FD = cast<FunctionDecl>(Redecl);
- auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
- // AST invariant: if any exception spec in the redecl chain is
- // resolved, all are resolved. We don't need to go any further.
- // FIXME: If the exception spec is resolved, check that it matches.
- break;
- }
+
+ // Update this declaration's exception specification, if needed.
+ auto *FD = cast<FunctionDecl>(D);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ // FIXME: If the exception specification is already present, check that it
+ // matches.
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
FD->setType(Reader.Context.getFunctionType(
FPT->getReturnType(), FPT->getParamTypes(),
FPT->getExtProtoInfo().withExceptionSpec(ESI)));
+
+ // When we get to the end of deserializing, see if there are other decls
+ // that we need to propagate this exception specification onto.
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(FD->getCanonicalDecl(), FD));
}
break;
}
@@ -3685,10 +3907,43 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_STATIC_LOCAL_NUMBER:
Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
break;
+
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
Reader.Context, ReadSourceRange(Record, Idx)));
break;
+
+ case UPD_DECL_EXPORTED: {
+ unsigned SubmoduleID = readSubmoduleID(Record, Idx);
+ auto *Exported = cast<NamedDecl>(D);
+ if (auto *TD = dyn_cast<TagDecl>(Exported))
+ Exported = TD->getDefinition();
+ Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
+ if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ // FIXME: This doesn't send the right notifications if there are
+ // ASTMutationListeners other than an ASTWriter.
+ Reader.getContext().mergeDefinitionIntoModule(
+ cast<NamedDecl>(Exported), Owner,
+ /*NotifyListeners*/ false);
+ Reader.PendingMergedDefinitionsToDeduplicate.insert(
+ cast<NamedDecl>(Exported));
+ } else if (Owner && Owner->NameVisibility != Module::AllVisible) {
+ // If Owner is made visible at some later point, make this declaration
+ // visible too.
+ Reader.HiddenNamesMap[Owner].push_back(Exported);
+ } else {
+ // The declaration is now visible.
+ Exported->Hidden = false;
+ }
+ break;
+ }
+
+ case UPD_ADDED_ATTR_TO_RECORD:
+ AttrVec Attrs;
+ Reader.ReadAttributes(F, Attrs, Record, Idx);
+ assert(Attrs.size() == 1);
+ D->addAttr(Attrs[0]);
+ break;
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
index d1b032b..5b1c4f4 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
@@ -68,8 +68,8 @@ public:
return a.Kind == b.Kind && a.Data == b.Data;
}
- hash_value_type ComputeHash(const DeclNameKey &Key) const;
- internal_key_type GetInternalKey(const external_key_type& Name) const;
+ static hash_value_type ComputeHash(const DeclNameKey &Key);
+ static internal_key_type GetInternalKey(const external_key_type& Name);
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 4ef2e73..ca5d0be 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -486,7 +486,7 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
// Read string data
SmallString<16> Str(&Record[Idx], &Record[Idx] + Len);
- E->setString(Reader.getContext(), Str.str(), kind, isPascal);
+ E->setString(Reader.getContext(), Str, kind, isPascal);
Idx += Len;
// Read source locations
@@ -801,6 +801,16 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
Designators.data(), Designators.size());
}
+void ASTStmtReader::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+ VisitExpr(E);
+ E->setBase(Reader.ReadSubExpr());
+ E->setUpdater(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitNoInitExpr(NoInitExpr *E) {
+ VisitExpr(E);
+}
+
void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
}
@@ -1775,6 +1785,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_flush:
C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_depend:
+ C = OMPDependClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1826,6 +1839,7 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
C->setScheduleKind(
static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
C->setChunkSize(Reader->Reader.ReadSubExpr());
+ C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
@@ -1889,6 +1903,22 @@ void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setSourceExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setDestinationExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setAssignmentOps(Vars);
}
void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
@@ -1917,6 +1947,18 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setReductionOps(Vars);
}
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
@@ -1928,7 +1970,20 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setInits(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setUpdates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setFinals(Vars);
C->setStep(Reader->Reader.ReadSubExpr());
+ C->setCalcStep(Reader->Reader.ReadSubExpr());
}
void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
@@ -1946,16 +2001,50 @@ void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
+ SmallVector<Expr *, 16> Exprs;
+ Exprs.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
- C->setVarRefs(Vars);
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setSourceExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setDestinationExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setAssignmentOps(Exprs);
}
void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Exprs;
+ Exprs.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setSourceExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setDestinationExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Reader->Reader.ReadSubExpr());
+ C->setAssignmentOps(Exprs);
+}
+
+void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
@@ -1963,8 +2052,11 @@ void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
C->setVarRefs(Vars);
}
-void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
+void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setDependencyKind(static_cast<OpenMPDependClauseKind>(Record[Idx++]));
+ C->setDependencyLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
@@ -1997,9 +2089,7 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
D->setLastIteration(Reader.ReadSubExpr());
D->setCalcLastIteration(Reader.ReadSubExpr());
D->setPreCond(Reader.ReadSubExpr());
- auto Fst = Reader.ReadSubExpr();
- auto Snd = Reader.ReadSubExpr();
- D->setCond(Fst, Snd);
+ D->setCond(Reader.ReadSubExpr());
D->setInit(Reader.ReadSubExpr());
D->setInc(Reader.ReadSubExpr());
if (isOpenMPWorksharingDirective(D->getDirectiveKind())) {
@@ -2115,6 +2205,11 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
@@ -2135,6 +2230,9 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
D->setX(Reader.ReadSubExpr());
D->setV(Reader.ReadSubExpr());
D->setExpr(Reader.ReadSubExpr());
+ D->setUpdateExpr(Reader.ReadSubExpr());
+ D->IsXLHSInRHSPart = Record[Idx++] != 0;
+ D->IsPostfixUpdate = Record[Idx++] != 0;
}
void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
@@ -2151,6 +2249,19 @@ void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPCancellationPointDirective(
+ OMPCancellationPointDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
+}
+
+void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2423,11 +2534,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx);
DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
bool IsArrow = Record[Idx++];
+ SourceLocation OperatorLoc = ReadSourceLocation(F, Record, Idx);
- S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc,
+ S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc,
TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo,
- HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr,
- T, VK, OK);
+ HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T,
+ VK, OK);
ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
MemberD->getDeclName(), Record, Idx);
if (HadMultipleCandidates)
@@ -2479,10 +2591,18 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
+ case EXPR_DESIGNATED_INIT_UPDATE:
+ S = new (Context) DesignatedInitUpdateExpr(Empty);
+ break;
+
case EXPR_IMPLICIT_VALUE_INIT:
S = new (Context) ImplicitValueInitExpr(Empty);
break;
+ case EXPR_NO_INIT:
+ S = new (Context) NoInitExpr(Empty);
+ break;
+
case EXPR_VA_ARG:
S = new (Context) VAArgExpr(Empty);
break;
@@ -2717,6 +2837,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = OMPTaskwaitDirective::CreateEmpty(Context, Empty);
break;
+ case STMT_OMP_TASKGROUP_DIRECTIVE:
+ S = OMPTaskgroupDirective::CreateEmpty(Context, Empty);
+ break;
+
case STMT_OMP_FLUSH_DIRECTIVE:
S = OMPFlushDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
@@ -2741,6 +2865,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_CANCELLATION_POINT_DIRECTIVE:
+ S = OMPCancellationPointDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_CANCEL_DIRECTIVE:
+ S = OMPCancelDirective::CreateEmpty(Context, Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 6c60d45..8b68638 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -60,14 +60,14 @@ using namespace clang;
using namespace clang::serialization;
template <typename T, typename Allocator>
-static StringRef data(const std::vector<T, Allocator> &v) {
+static StringRef bytes(const std::vector<T, Allocator> &v) {
if (v.empty()) return StringRef();
return StringRef(reinterpret_cast<const char*>(&v[0]),
sizeof(T) * v.size());
}
template <typename T>
-static StringRef data(const SmallVectorImpl<T> &v) {
+static StringRef bytes(const SmallVectorImpl<T> &v) {
return StringRef(reinterpret_cast<const char*>(v.data()),
sizeof(T) * v.size());
}
@@ -421,9 +421,13 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
+ Record.push_back(T->getTypeArgsAsWritten().size());
+ for (auto TypeArg : T->getTypeArgsAsWritten())
+ Writer.AddTypeRef(TypeArg, Record);
Record.push_back(T->getNumProtocols());
for (const auto *I : T->quals())
Writer.AddDeclRef(I, Record);
+ Record.push_back(T->isKindOfTypeAsWritten());
Code = TYPE_OBJC_OBJECT;
}
@@ -648,8 +652,12 @@ void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
}
void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
Record.push_back(TL.hasBaseTypeAsWritten());
- Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
- Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getTypeArgsLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getTypeArgsRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
+ Writer.AddTypeSourceInfo(TL.getTypeArgTInfo(i), Record);
+ Writer.AddSourceLocation(TL.getProtocolLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getProtocolRAngleLoc(), Record);
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
}
@@ -774,7 +782,9 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
RECORD(EXPR_EXT_VECTOR_ELEMENT);
RECORD(EXPR_INIT_LIST);
RECORD(EXPR_DESIGNATED_INIT);
+ RECORD(EXPR_DESIGNATED_INIT_UPDATE);
RECORD(EXPR_IMPLICIT_VALUE_INIT);
+ RECORD(EXPR_NO_INIT);
RECORD(EXPR_VA_ARG);
RECORD(EXPR_ADDR_LABEL);
RECORD(EXPR_STMT);
@@ -867,6 +877,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(MODULE_NAME);
RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
+ RECORD(KNOWN_MODULE_FILES);
RECORD(LANGUAGE_OPTIONS);
RECORD(TARGET_OPTIONS);
RECORD(ORIGINAL_FILE);
@@ -892,7 +903,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
RECORD(UNUSED_FILESCOPED_DECLS);
- RECORD(LOCALLY_SCOPED_EXTERN_C_DECLS);
RECORD(SELECTOR_OFFSETS);
RECORD(METHOD_POOL);
RECORD(PP_COUNTER_VALUE);
@@ -924,11 +934,9 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(OBJC_CATEGORIES_MAP);
RECORD(FILE_SORTED_DECLS);
RECORD(IMPORTED_MODULES);
- RECORD(MERGED_DECLARATIONS);
RECORD(LOCAL_REDECLARATIONS);
RECORD(OBJC_CATEGORIES);
RECORD(MACRO_OFFSET);
- RECORD(MACRO_TABLE);
RECORD(LATE_PARSED_TEMPLATE);
RECORD(OPTIMIZE_PRAGMA_OPTIONS);
@@ -941,10 +949,12 @@ void ASTWriter::WriteBlockInfoBlock() {
// Preprocessor Block.
BLOCK(PREPROCESSOR_BLOCK);
- RECORD(PP_MACRO_OBJECT_LIKE);
+ RECORD(PP_MACRO_DIRECTIVE_HISTORY);
RECORD(PP_MACRO_FUNCTION_LIKE);
+ RECORD(PP_MACRO_OBJECT_LIKE);
+ RECORD(PP_MODULE_MACRO);
RECORD(PP_TOKEN);
-
+
// Decls and Types block.
BLOCK(DECLTYPES_BLOCK);
RECORD(TYPE_EXT_QUAL);
@@ -1062,7 +1072,8 @@ void ASTWriter::WriteBlockInfoBlock() {
/// to an absolute path and removing nested './'s.
///
/// \return \c true if the path was changed.
-bool cleanPathForOutput(FileManager &FileMgr, SmallVectorImpl<char> &Path) {
+static bool cleanPathForOutput(FileManager &FileMgr,
+ SmallVectorImpl<char> &Path) {
bool Changed = false;
if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
@@ -1159,12 +1170,17 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
- // Signature
- Record.clear();
- Record.push_back(getSignature());
- Stream.EmitRecord(SIGNATURE, Record);
-
if (WritingModule) {
+ // For implicit modules we output a signature that we can use to ensure
+ // duplicate module builds don't collide in the cache as their output order
+ // is non-deterministic.
+ // FIXME: Remove this when output is deterministic.
+ if (Context.getLangOpts().ImplicitModules) {
+ Record.clear();
+ Record.push_back(getSignature());
+ Stream.EmitRecord(SIGNATURE, Record);
+ }
+
// Module name
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
@@ -1222,20 +1238,28 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
serialization::ModuleManager &Mgr = Chain->getModuleManager();
Record.clear();
- for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();
- M != MEnd; ++M) {
+ for (auto *M : Mgr) {
// Skip modules that weren't directly imported.
- if (!(*M)->isDirectlyImported())
+ if (!M->isDirectlyImported())
continue;
- Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding
- AddSourceLocation((*M)->ImportLoc, Record);
- Record.push_back((*M)->File->getSize());
- Record.push_back((*M)->File->getModificationTime());
- Record.push_back((*M)->Signature);
- AddPath((*M)->FileName, Record);
+ Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding
+ AddSourceLocation(M->ImportLoc, Record);
+ Record.push_back(M->File->getSize());
+ Record.push_back(M->File->getModificationTime());
+ Record.push_back(M->Signature);
+ AddPath(M->FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
+
+ // Also emit a list of known module files that were not imported,
+ // but are made available by this module.
+ // FIXME: Should we also include a signature here?
+ Record.clear();
+ for (auto *E : Mgr.getAdditionalKnownModuleFiles())
+ AddPath(E->getName(), Record);
+ if (!Record.empty())
+ Stream.EmitRecord(KNOWN_MODULE_FILES, Record);
}
// Language options.
@@ -1250,11 +1274,14 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID));
#include "clang/Basic/Sanitizers.def"
+ Record.push_back(LangOpts.ModuleFeatures.size());
+ for (StringRef Feature : LangOpts.ModuleFeatures)
+ AddString(Feature, Record);
+
Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);
-
- Record.push_back(LangOpts.CurrentModule.size());
- Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end());
+
+ AddString(LangOpts.CurrentModule, Record);
// Comment options.
Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size());
@@ -1341,6 +1368,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back(HSOpts.UseStandardSystemIncludes);
Record.push_back(HSOpts.UseStandardCXXIncludes);
Record.push_back(HSOpts.UseLibcxx);
+ // Write out the specific module cache path that contains the module files.
+ AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record);
Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);
// Preprocessor options.
@@ -1467,7 +1496,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
unsigned UserFilesNum = 0;
// Write out all of the input files.
- std::vector<uint32_t> InputFileOffsets;
+ std::vector<uint64_t> InputFileOffsets;
for (std::deque<InputFileEntry>::iterator
I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) {
const InputFileEntry &Entry = *I;
@@ -1514,7 +1543,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
Record.push_back(INPUT_FILE_OFFSETS);
Record.push_back(InputFileOffsets.size());
Record.push_back(UserFilesNum);
- Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets));
+ Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));
}
//===----------------------------------------------------------------------===//
@@ -1756,7 +1785,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
Record.push_back(NumHeaderSearchEntries);
Record.push_back(TableData.size());
TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());
- Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData.str());
+ Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);
// Free all of the strings we had to duplicate.
for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)
@@ -1909,7 +1938,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(SOURCE_LOCATION_OFFSETS);
Record.push_back(SLocEntryOffsets.size());
Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy
- Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets));
+ Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets));
// Write the source location entry preloads array, telling the AST
// reader which source locations entries it should load eagerly.
@@ -1956,52 +1985,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Preprocessor Serialization
//===----------------------------------------------------------------------===//
-namespace {
-class ASTMacroTableTrait {
-public:
- typedef IdentID key_type;
- typedef key_type key_type_ref;
-
- struct Data {
- uint32_t MacroDirectivesOffset;
- };
-
- typedef Data data_type;
- typedef const data_type &data_type_ref;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
-
- static hash_value_type ComputeHash(IdentID IdID) {
- return llvm::hash_value(IdID);
- }
-
- std::pair<unsigned,unsigned>
- static EmitKeyDataLength(raw_ostream& Out,
- key_type_ref Key, data_type_ref Data) {
- unsigned KeyLen = 4; // IdentID.
- unsigned DataLen = 4; // MacroDirectivesOffset.
- return std::make_pair(KeyLen, DataLen);
- }
-
- static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(Key);
- }
-
- static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
- unsigned) {
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset);
- }
-};
-} // end anonymous namespace
-
-static int compareMacroDirectives(
- const std::pair<const IdentifierInfo *, MacroDirective *> *X,
- const std::pair<const IdentifierInfo *, MacroDirective *> *Y) {
- return X->first->getName().compare(Y->first->getName());
-}
-
static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
const Preprocessor &PP) {
if (MacroInfo *MI = MD->getMacroInfo())
@@ -2009,10 +1992,6 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
return true;
if (IsModule) {
- // Re-export any imported directives.
- if (MD->isImported())
- return false;
-
SourceLocation Loc = MD->getLocation();
if (Loc.isInvalid())
return true;
@@ -2032,6 +2011,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
WritePreprocessorDetail(*PPRec);
RecordData Record;
+ RecordData ModuleMacroRecord;
// If the preprocessor __COUNTER__ value has been bumped, remember it.
if (PP.getCounterValue() != 0) {
@@ -2052,75 +2032,75 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// Loop over all the macro directives that are live at the end of the file,
// emitting each to the PP section.
- // Construct the list of macro directives that need to be serialized.
- SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2>
- MacroDirectives;
- for (Preprocessor::macro_iterator
- I = PP.macro_begin(/*IncludeExternalMacros=*/false),
- E = PP.macro_end(/*IncludeExternalMacros=*/false);
- I != E; ++I) {
- MacroDirectives.push_back(std::make_pair(I->first, I->second));
- }
-
+ // Construct the list of identifiers with macro directives that need to be
+ // serialized.
+ SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;
+ for (auto &Id : PP.getIdentifierTable())
+ if (Id.second->hadMacroDefinition() &&
+ (!Id.second->isFromAST() ||
+ Id.second->hasChangedSinceDeserialization()))
+ MacroIdentifiers.push_back(Id.second);
// Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering.
- llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(),
- &compareMacroDirectives);
-
- llvm::OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator;
+ std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
+ llvm::less_ptr<IdentifierInfo>());
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
- for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) {
- const IdentifierInfo *Name = MacroDirectives[I].first;
- uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo();
- MacroDirective *MD = MacroDirectives[I].second;
-
- // If the macro or identifier need no updates, don't write the macro history
- // for this one.
- // FIXME: Chain the macro history instead of re-writing it.
- if (MD->isFromPCH() &&
- Name->isFromAST() && !Name->hasChangedSinceDeserialization())
- continue;
+ for (const IdentifierInfo *Name : MacroIdentifiers) {
+ MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);
+ auto StartOffset = Stream.GetCurrentBitNo();
// Emit the macro directives in reverse source order.
for (; MD; MD = MD->getPrevious()) {
+ // Once we hit an ignored macro, we're done: the rest of the chain
+ // will all be ignored macros.
if (shouldIgnoreMacro(MD, IsModule, PP))
- continue;
+ break;
AddSourceLocation(MD->getLocation(), Record);
Record.push_back(MD->getKind());
if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- MacroID InfoID = getMacroRef(DefMD->getInfo(), Name);
- Record.push_back(InfoID);
- Record.push_back(DefMD->getOwningModuleID());
- Record.push_back(DefMD->isAmbiguous());
- } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
- Record.push_back(UndefMD->getOwningModuleID());
- } else {
- auto *VisMD = cast<VisibilityMacroDirective>(MD);
+ Record.push_back(getMacroRef(DefMD->getInfo(), Name));
+ } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
Record.push_back(VisMD->isPublic());
}
+ }
- if (MD->isImported()) {
- auto Overrides = MD->getOverriddenModules();
- Record.push_back(Overrides.size());
- for (auto Override : Overrides)
- Record.push_back(Override);
+ // Write out any exported module macros.
+ bool EmittedModuleMacros = false;
+ if (IsModule) {
+ auto Leafs = PP.getLeafModuleMacros(Name);
+ SmallVector<ModuleMacro*, 8> Worklist(Leafs.begin(), Leafs.end());
+ llvm::DenseMap<ModuleMacro*, unsigned> Visits;
+ while (!Worklist.empty()) {
+ auto *Macro = Worklist.pop_back_val();
+
+ // Emit a record indicating this submodule exports this macro.
+ ModuleMacroRecord.push_back(
+ getSubmoduleID(Macro->getOwningModule()));
+ ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name));
+ for (auto *M : Macro->overrides())
+ ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));
+
+ Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);
+ ModuleMacroRecord.clear();
+
+ // Enqueue overridden macros once we've visited all their ancestors.
+ for (auto *M : Macro->overrides())
+ if (++Visits[M] == M->getNumOverridingMacros())
+ Worklist.push_back(M);
+
+ EmittedModuleMacros = true;
}
}
- if (Record.empty())
+
+ if (Record.empty() && !EmittedModuleMacros)
continue;
+ IdentMacroDirectivesOffsetMap[Name] = StartOffset;
Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);
Record.clear();
-
- IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset;
-
- IdentID NameID = getIdentifierRef(Name);
- ASTMacroTableTrait::Data data;
- data.MacroDirectivesOffset = MacroDirectiveOffset;
- Generator.insert(NameID, data);
}
/// \brief Offsets of each of the macros into the bitstream, indexed by
@@ -2168,9 +2148,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.push_back(MI->isGNUVarargs());
Record.push_back(MI->hasCommaPasting());
Record.push_back(MI->getNumArgs());
- for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
- I != E; ++I)
- AddIdentifierRef(*I, Record);
+ for (const IdentifierInfo *Arg : MI->args())
+ AddIdentifierRef(Arg, Record);
}
// If we have a detailed preprocessing record, record the macro definition
@@ -2196,33 +2175,9 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Stream.ExitBlock();
- // Create the on-disk hash table in a buffer.
- SmallString<4096> MacroTable;
- uint32_t BucketOffset;
- {
- using namespace llvm::support;
- llvm::raw_svector_ostream Out(MacroTable);
- // Make sure that no bucket is at offset 0
- endian::Writer<little>(Out).write<uint32_t>(0);
- BucketOffset = Generator.Emit(Out);
- }
-
- // Write the macro table
- using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev);
-
- Record.push_back(MACRO_TABLE);
- Record.push_back(BucketOffset);
- Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable.str());
- Record.clear();
-
// Write the offsets table for macro IDs.
using namespace llvm;
- Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID
@@ -2234,7 +2189,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.push_back(MacroOffsets.size());
Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS);
Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record,
- data(MacroOffsets));
+ bytes(MacroOffsets));
}
void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
@@ -2274,13 +2229,13 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
(void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {
Record.clear();
- PreprocessedEntityOffsets.push_back(PPEntityOffset((*E)->getSourceRange(),
- Stream.GetCurrentBitNo()));
+ PreprocessedEntityOffsets.push_back(
+ PPEntityOffset((*E)->getSourceRange(), Stream.GetCurrentBitNo()));
- if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ if (MacroDefinitionRecord *MD = dyn_cast<MacroDefinitionRecord>(*E)) {
// Record this macro definition's ID.
MacroDefinitions[MD] = NextPreprocessorEntityID;
-
+
AddIdentifierRef(MD->getName(), Record);
Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);
continue;
@@ -2332,7 +2287,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Record.push_back(PPD_ENTITIES_OFFSETS);
Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS);
Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
- data(PreprocessedEntityOffsets));
+ bytes(PreprocessedEntityOffsets));
}
}
@@ -2369,19 +2324,6 @@ static unsigned getNumberOfModules(Module *Mod) {
}
void ASTWriter::WriteSubmodules(Module *WritingModule) {
- // Determine the dependencies of our module and each of it's submodules.
- // FIXME: This feels like it belongs somewhere else, but there are no
- // other consumers of this information.
- SourceManager &SrcMgr = PP->getSourceManager();
- ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
- for (const auto *I : Context->local_imports()) {
- if (Module *ImportedFrom
- = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),
- SrcMgr))) {
- ImportedFrom->Imports.push_back(I->getImportedModule());
- }
- }
-
// Enter the submodule description block.
Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);
@@ -2509,16 +2451,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
}
// Emit the umbrella header, if there is one.
- if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) {
+ if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) {
Record.clear();
Record.push_back(SUBMODULE_UMBRELLA_HEADER);
- Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,
- UmbrellaHeader->getName());
- } else if (const DirectoryEntry *UmbrellaDir = Mod->getUmbrellaDir()) {
+ Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,
+ UmbrellaHeader.NameAsWritten);
+ } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) {
Record.clear();
Record.push_back(SUBMODULE_UMBRELLA_DIR);
Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,
- UmbrellaDir->getName());
+ UmbrellaDir.NameAsWritten);
}
// Emit the headers.
@@ -2566,8 +2508,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Record.clear();
for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {
if (Module *Exported = Mod->Exports[I].getPointer()) {
- unsigned ExportedID = SubmoduleIDs[Exported];
- assert(ExportedID > 0 && "Unknown submodule ID?");
+ unsigned ExportedID = getSubmoduleID(Exported);
Record.push_back(ExportedID);
} else {
Record.push_back(0);
@@ -2618,9 +2559,14 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
}
Stream.ExitBlock();
-
- assert((NextSubmoduleID - FirstSubmoduleID
- == getNumberOfModules(WritingModule)) && "Wrong # of submodules");
+
+ // FIXME: This can easily happen, if we have a reference to a submodule that
+ // did not result in us loading a module file for that submodule. For
+ // instance, a cross-top-level-module 'conflict' declaration will hit this.
+ assert((NextSubmoduleID - FirstSubmoduleID ==
+ getNumberOfModules(WritingModule)) &&
+ "Wrong # of submodules; found a reference to a non-local, "
+ "non-imported submodule?");
}
serialization::SubmoduleID
@@ -2684,6 +2630,29 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
}
+void ASTWriter::WriteCXXCtorInitializersOffsets() {
+ if (CXXCtorInitializersOffsets.empty())
+ return;
+
+ RecordData Record;
+
+ // Create a blob abbreviation for the C++ ctor initializer offsets.
+ using namespace llvm;
+
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(CXX_CTOR_INITIALIZERS_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned CtorInitializersOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the base specifier offsets table.
+ Record.clear();
+ Record.push_back(CXX_CTOR_INITIALIZERS_OFFSETS);
+ Record.push_back(CXXCtorInitializersOffsets.size());
+ Stream.EmitRecordWithBlob(CtorInitializersOffsetAbbrev, Record,
+ bytes(CXXCtorInitializersOffsets));
+}
+
void ASTWriter::WriteCXXBaseSpecifiersOffsets() {
if (CXXBaseSpecifiersOffsets.empty())
return;
@@ -2704,7 +2673,7 @@ void ASTWriter::WriteCXXBaseSpecifiersOffsets() {
Record.push_back(CXX_BASE_SPECIFIER_OFFSETS);
Record.push_back(CXXBaseSpecifiersOffsets.size());
Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record,
- data(CXXBaseSpecifiersOffsets));
+ bytes(CXXBaseSpecifiersOffsets));
}
//===----------------------------------------------------------------------===//
@@ -2780,7 +2749,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D)));
++NumLexicalDeclContexts;
- Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls));
+ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls));
return Offset;
}
@@ -2799,7 +2768,7 @@ void ASTWriter::WriteTypeDeclOffsets() {
Record.push_back(TYPE_OFFSET);
Record.push_back(TypeOffsets.size());
Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS);
- Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets));
+ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
// Write the declaration offsets array
Abbrev = new BitCodeAbbrev();
@@ -2812,22 +2781,25 @@ void ASTWriter::WriteTypeDeclOffsets() {
Record.push_back(DECL_OFFSET);
Record.push_back(DeclOffsets.size());
Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS);
- Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets));
+ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
}
void ASTWriter::WriteFileDeclIDsMap() {
using namespace llvm;
RecordData Record;
+ SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs(
+ FileDeclIDs.begin(), FileDeclIDs.end());
+ std::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
+ llvm::less_first());
+
// Join the vectors of DeclIDs from all files.
- SmallVector<DeclID, 256> FileSortedIDs;
- for (FileDeclIDsTy::iterator
- FI = FileDeclIDs.begin(), FE = FileDeclIDs.end(); FI != FE; ++FI) {
- DeclIDInFileInfo &Info = *FI->second;
- Info.FirstDeclIndex = FileSortedIDs.size();
- for (LocDeclIDsTy::iterator
- DI = Info.DeclIDs.begin(), DE = Info.DeclIDs.end(); DI != DE; ++DI)
- FileSortedIDs.push_back(DI->second);
+ SmallVector<DeclID, 256> FileGroupedDeclIDs;
+ for (auto &FileDeclEntry : SortedFileDeclIDs) {
+ DeclIDInFileInfo &Info = *FileDeclEntry.second;
+ Info.FirstDeclIndex = FileGroupedDeclIDs.size();
+ for (auto &LocDeclEntry : Info.DeclIDs)
+ FileGroupedDeclIDs.push_back(LocDeclEntry.second);
}
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
@@ -2836,8 +2808,8 @@ void ASTWriter::WriteFileDeclIDsMap() {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
Record.push_back(FILE_SORTED_DECLS);
- Record.push_back(FileSortedIDs.size());
- Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs));
+ Record.push_back(FileGroupedDeclIDs.size());
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs));
}
void ASTWriter::WriteComments() {
@@ -2988,13 +2960,12 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
// Create the on-disk hash table representation. We walk through every
// selector we've seen and look it up in the method pool.
SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
- for (llvm::DenseMap<Selector, SelectorID>::iterator
- I = SelectorIDs.begin(), E = SelectorIDs.end();
- I != E; ++I) {
- Selector S = I->first;
+ for (auto &SelectorAndID : SelectorIDs) {
+ Selector S = SelectorAndID.first;
+ SelectorID ID = SelectorAndID.second;
Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
ASTMethodPoolTrait::data_type Data = {
- I->second,
+ ID,
ObjCMethodList(),
ObjCMethodList()
};
@@ -3004,7 +2975,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
}
// Only write this selector if it's not in an existing AST or something
// changed.
- if (Chain && I->second < FirstSelectorID) {
+ if (Chain && ID < FirstSelectorID) {
// Selector already exists. Did it change?
bool changed = false;
for (ObjCMethodList *M = &Data.Instance;
@@ -3051,7 +3022,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
Record.push_back(METHOD_POOL);
Record.push_back(BucketOffset);
Record.push_back(NumTableEntries);
- Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
+ Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);
// Create a blob abbreviation for the selector table offsets.
Abbrev = new BitCodeAbbrev();
@@ -3067,7 +3038,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
Record.push_back(SelectorOffsets.size());
Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS);
Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
- data(SelectorOffsets));
+ bytes(SelectorOffsets));
}
}
@@ -3082,11 +3053,9 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
// Note: this writes out all references even for a dependent AST. But it is
// very tricky to fix, and given that @selector shouldn't really appear in
// headers, probably not worth it. It's not a correctness issue.
- for (DenseMap<Selector, SourceLocation>::iterator S =
- SemaRef.ReferencedSelectors.begin(),
- E = SemaRef.ReferencedSelectors.end(); S != E; ++S) {
- Selector Sel = (*S).first;
- SourceLocation Loc = (*S).second;
+ for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) {
+ Selector Sel = SelectorAndLocation.first;
+ SourceLocation Loc = SelectorAndLocation.second;
AddSelectorRef(Sel, Record);
AddSourceLocation(Loc, Record);
}
@@ -3097,174 +3066,59 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
// Identifier Table Serialization
//===----------------------------------------------------------------------===//
+/// Determine the declaration that should be put into the name lookup table to
+/// represent the given declaration in this module. This is usually D itself,
+/// but if D was imported and merged into a local declaration, we want the most
+/// recent local declaration instead. The chosen declaration will be the most
+/// recent declaration in any module that imports this one.
+static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,
+ NamedDecl *D) {
+ if (!LangOpts.Modules || !D->isFromASTFile())
+ return D;
+
+ if (Decl *Redecl = D->getPreviousDecl()) {
+ // For Redeclarable decls, a prior declaration might be local.
+ for (; Redecl; Redecl = Redecl->getPreviousDecl()) {
+ if (!Redecl->isFromASTFile())
+ return cast<NamedDecl>(Redecl);
+ // If we find a decl from a (chained-)PCH stop since we won't find a
+ // local one.
+ if (D->getOwningModuleID() == 0)
+ break;
+ }
+ } else if (Decl *First = D->getCanonicalDecl()) {
+ // For Mergeable decls, the first decl might be local.
+ if (!First->isFromASTFile())
+ return cast<NamedDecl>(First);
+ }
+
+ // All declarations are imported. Our most recent declaration will also be
+ // the most recent one in anyone who imports us.
+ return D;
+}
+
namespace {
class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
IdentifierResolver &IdResolver;
- bool IsModule;
- /// \brief Determines whether this is an "interesting" identifier
- /// that needs a full IdentifierInfo structure written into the hash
- /// table.
- bool isInterestingIdentifier(IdentifierInfo *II, MacroDirective *&Macro) {
- if (II->isPoisoned() ||
+ /// \brief Determines whether this is an "interesting" identifier that needs a
+ /// full IdentifierInfo structure written into the hash table. Notably, this
+ /// doesn't check whether the name has macros defined; use PublicMacroIterator
+ /// to check that.
+ bool isInterestingIdentifier(IdentifierInfo *II, uint64_t MacroOffset) {
+ if (MacroOffset ||
+ II->isPoisoned() ||
II->isExtensionToken() ||
II->getObjCOrBuiltinID() ||
II->hasRevertedTokenIDToIdentifier() ||
II->getFETokenInfo<void>())
return true;
- return hadMacroDefinition(II, Macro);
- }
-
- bool hadMacroDefinition(IdentifierInfo *II, MacroDirective *&Macro) {
- if (!II->hadMacroDefinition())
- return false;
-
- if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) {
- if (!IsModule)
- return !shouldIgnoreMacro(Macro, IsModule, PP);
-
- MacroState State;
- if (getFirstPublicSubmoduleMacro(Macro, State))
- return true;
- }
-
return false;
}
- enum class SubmoduleMacroState {
- /// We've seen nothing about this macro.
- None,
- /// We've seen a public visibility directive.
- Public,
- /// We've either exported a macro for this module or found that the
- /// module's definition of this macro is private.
- Done
- };
- typedef llvm::DenseMap<SubmoduleID, SubmoduleMacroState> MacroState;
-
- MacroDirective *
- getFirstPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) {
- if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, State))
- return NextMD;
- return nullptr;
- }
-
- MacroDirective *
- getNextPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) {
- if (MacroDirective *NextMD =
- getPublicSubmoduleMacro(MD->getPrevious(), State))
- return NextMD;
- return nullptr;
- }
-
- /// \brief Traverses the macro directives history and returns the next
- /// public macro definition or undefinition that has not been found so far.
- ///
- /// A macro that is defined in submodule A and undefined in submodule B
- /// will still be considered as defined/exported from submodule A.
- MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
- MacroState &State) {
- if (!MD)
- return nullptr;
-
- Optional<bool> IsPublic;
- for (; MD; MD = MD->getPrevious()) {
- // Once we hit an ignored macro, we're done: the rest of the chain
- // will all be ignored macros.
- if (shouldIgnoreMacro(MD, IsModule, PP))
- break;
-
- // If this macro was imported, re-export it.
- if (MD->isImported())
- return MD;
-
- SubmoduleID ModID = getSubmoduleID(MD);
- auto &S = State[ModID];
- assert(ModID && "found macro in no submodule");
-
- if (S == SubmoduleMacroState::Done)
- continue;
-
- if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
- // The latest visibility directive for a name in a submodule affects all
- // the directives that come before it.
- if (S == SubmoduleMacroState::None)
- S = VisMD->isPublic() ? SubmoduleMacroState::Public
- : SubmoduleMacroState::Done;
- } else {
- S = SubmoduleMacroState::Done;
- return MD;
- }
- }
-
- return nullptr;
- }
-
- ArrayRef<SubmoduleID>
- getOverriddenSubmodules(MacroDirective *MD,
- SmallVectorImpl<SubmoduleID> &ScratchSpace) {
- assert(!isa<VisibilityMacroDirective>(MD) &&
- "only #define and #undef can override");
- if (MD->isImported())
- return MD->getOverriddenModules();
-
- ScratchSpace.clear();
- SubmoduleID ModID = getSubmoduleID(MD);
- for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) {
- if (shouldIgnoreMacro(MD, IsModule, PP))
- break;
-
- // If this is a definition from a submodule import, that submodule's
- // definition is overridden by the definition or undefinition that we
- // started with.
- if (MD->isImported()) {
- if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID();
- assert(DefModuleID && "imported macro has no owning module");
- ScratchSpace.push_back(DefModuleID);
- } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
- // If we override a #undef, we override anything that #undef overrides.
- // We don't need to override it, since an active #undef doesn't affect
- // the meaning of a macro.
- auto Overrides = UndefMD->getOverriddenModules();
- ScratchSpace.insert(ScratchSpace.end(),
- Overrides.begin(), Overrides.end());
- }
- }
-
- // Stop once we leave the original macro's submodule.
- //
- // Either this submodule #included another submodule of the same
- // module or it just happened to be built after the other module.
- // In the former case, we override the submodule's macro.
- //
- // FIXME: In the latter case, we shouldn't do so, but we can't tell
- // these cases apart.
- //
- // FIXME: We can leave this submodule and re-enter it if it #includes a
- // header within a different submodule of the same module. In such cases
- // the overrides list will be incomplete.
- SubmoduleID DirectiveModuleID = getSubmoduleID(MD);
- if (DirectiveModuleID != ModID) {
- if (DirectiveModuleID && !MD->isImported())
- ScratchSpace.push_back(DirectiveModuleID);
- break;
- }
- }
-
- std::sort(ScratchSpace.begin(), ScratchSpace.end());
- ScratchSpace.erase(std::unique(ScratchSpace.begin(), ScratchSpace.end()),
- ScratchSpace.end());
- return ScratchSpace;
- }
-
- SubmoduleID getSubmoduleID(MacroDirective *MD) {
- return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
- }
-
public:
typedef IdentifierInfo* key_type;
typedef key_type key_type_ref;
@@ -3275,9 +3129,9 @@ public:
typedef unsigned hash_value_type;
typedef unsigned offset_type;
- ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
- IdentifierResolver &IdResolver, bool IsModule)
- : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { }
+ ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
+ IdentifierResolver &IdResolver)
+ : Writer(Writer), PP(PP), IdResolver(IdResolver) {}
static hash_value_type ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName());
@@ -3287,25 +3141,12 @@ public:
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
- MacroDirective *Macro = nullptr;
- if (isInterestingIdentifier(II, Macro)) {
+ auto MacroOffset = Writer.getMacroDirectivesOffset(II);
+ if (isInterestingIdentifier(II, MacroOffset)) {
DataLen += 2; // 2 bytes for builtin ID
DataLen += 2; // 2 bytes for flags
- if (hadMacroDefinition(II, Macro)) {
+ if (MacroOffset)
DataLen += 4; // MacroDirectives offset.
- if (IsModule) {
- MacroState State;
- SmallVector<SubmoduleID, 16> Scratch;
- for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State);
- MD; MD = getNextPublicSubmoduleMacro(MD, State)) {
- DataLen += 4; // MacroInfo ID or ModuleID.
- if (unsigned NumOverrides =
- getOverriddenSubmodules(MD, Scratch).size())
- DataLen += 4 * (1 + NumOverrides);
- }
- DataLen += 4; // 0 terminator.
- }
- }
for (IdentifierResolver::iterator D = IdResolver.begin(II),
DEnd = IdResolver.end();
@@ -3315,6 +3156,7 @@ public:
using namespace llvm::support;
endian::Writer<little> LE(Out);
+ assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen);
LE.write<uint16_t>(DataLen);
// We emit the key length after the data length so that every
// string is preceded by a 16-bit length. This matches the PTH
@@ -3331,25 +3173,13 @@ public:
Out.write(II->getNameStart(), KeyLen);
}
- static void emitMacroOverrides(raw_ostream &Out,
- ArrayRef<SubmoduleID> Overridden) {
- if (!Overridden.empty()) {
- using namespace llvm::support;
- endian::Writer<little> LE(Out);
- LE.write<uint32_t>(Overridden.size() | 0x80000000U);
- for (unsigned I = 0, N = Overridden.size(); I != N; ++I) {
- assert(Overridden[I] && "zero module ID for override");
- LE.write<uint32_t>(Overridden[I]);
- }
- }
- }
-
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- MacroDirective *Macro = nullptr;
- if (!isInterestingIdentifier(II, Macro)) {
+
+ auto MacroOffset = Writer.getMacroDirectivesOffset(II);
+ if (!isInterestingIdentifier(II, MacroOffset)) {
LE.write<uint32_t>(ID << 1);
return;
}
@@ -3359,77 +3189,29 @@ public:
assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
LE.write<uint16_t>(Bits);
Bits = 0;
- bool HadMacroDefinition = hadMacroDefinition(II, Macro);
+ bool HadMacroDefinition = MacroOffset != 0;
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
- Bits = (Bits << 1) | unsigned(IsModule);
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
Bits = (Bits << 1) | unsigned(II->isPoisoned());
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
LE.write<uint16_t>(Bits);
- if (HadMacroDefinition) {
- LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
- if (IsModule) {
- // Write the IDs of macros coming from different submodules.
- MacroState State;
- SmallVector<SubmoduleID, 16> Scratch;
- for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State);
- MD; MD = getNextPublicSubmoduleMacro(MD, State)) {
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- // FIXME: If this macro directive was created by #pragma pop_macros,
- // or if it was created implicitly by resolving conflicting macros,
- // it may be for a different submodule from the one in the MacroInfo
- // object. If so, we should write out its owning ModuleID.
- MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
- assert(InfoID);
- LE.write<uint32_t>(InfoID << 1);
- } else {
- auto *UndefMD = cast<UndefMacroDirective>(MD);
- SubmoduleID Mod = UndefMD->isImported()
- ? UndefMD->getOwningModuleID()
- : getSubmoduleID(UndefMD);
- LE.write<uint32_t>((Mod << 1) | 1);
- }
- emitMacroOverrides(Out, getOverriddenSubmodules(MD, Scratch));
- }
- LE.write<uint32_t>(0xdeadbeef);
- }
- }
+ if (HadMacroDefinition)
+ LE.write<uint32_t>(MacroOffset);
// Emit the declaration IDs in reverse order, because the
// IdentifierResolver provides the declarations as they would be
// visible (e.g., the function "stat" would come before the struct
- // "stat"), but the ASTReader adds declarations to the end of the list
- // (so we need to see the struct "status" before the function "status").
+ // "stat"), but the ASTReader adds declarations to the end of the list
+ // (so we need to see the struct "stat" before the function "stat").
// Only emit declarations that aren't from a chained PCH, though.
- SmallVector<Decl *, 16> Decls(IdResolver.begin(II),
- IdResolver.end());
- for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(),
- DEnd = Decls.rend();
+ SmallVector<NamedDecl *, 16> Decls(IdResolver.begin(II), IdResolver.end());
+ for (SmallVectorImpl<NamedDecl *>::reverse_iterator D = Decls.rbegin(),
+ DEnd = Decls.rend();
D != DEnd; ++D)
- LE.write<uint32_t>(Writer.getDeclID(getMostRecentLocalDecl(*D)));
- }
-
- /// \brief Returns the most recent local decl or the given decl if there are
- /// no local ones. The given decl is assumed to be the most recent one.
- Decl *getMostRecentLocalDecl(Decl *Orig) {
- // The only way a "from AST file" decl would be more recent from a local one
- // is if it came from a module.
- if (!PP.getLangOpts().Modules)
- return Orig;
-
- // Look for a local in the decl chain.
- for (Decl *D = Orig; D; D = D->getPreviousDecl()) {
- if (!D->isFromASTFile())
- return D;
- // If we come up a decl from a (chained-)PCH stop since we won't find a
- // local one.
- if (D->getOwningModuleID() == 0)
- break;
- }
-
- return Orig;
+ LE.write<uint32_t>(
+ Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D)));
}
};
} // end anonymous namespace
@@ -3448,29 +3230,33 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
// strings.
{
llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
- ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
+ ASTIdentifierTableTrait Trait(*this, PP, IdResolver);
// Look for any identifiers that were named while processing the
// headers, but are otherwise not needed. We add these to the hash
// table to enable checking of the predefines buffer in the case
// where the user adds new macro definitions when building the AST
// file.
+ SmallVector<const IdentifierInfo *, 128> IIs;
for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
IDEnd = PP.getIdentifierTable().end();
ID != IDEnd; ++ID)
- getIdentifierRef(ID->second);
+ IIs.push_back(ID->second);
+ // Sort the identifiers lexicographically before getting them references so
+ // that their order is stable.
+ std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ for (const IdentifierInfo *II : IIs)
+ getIdentifierRef(II);
// Create the on-disk hash table representation. We only store offsets
// for identifiers that appear here for the first time.
IdentifierOffsets.resize(NextIdentID - FirstIdentID);
- for (llvm::DenseMap<const IdentifierInfo *, IdentID>::iterator
- ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
- ID != IDEnd; ++ID) {
- assert(ID->first && "NULL identifier in identifier table");
- if (!Chain || !ID->first->isFromAST() ||
- ID->first->hasChangedSinceDeserialization())
- Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second,
- Trait);
+ for (auto IdentIDPair : IdentifierIDs) {
+ IdentifierInfo *II = const_cast<IdentifierInfo *>(IdentIDPair.first);
+ IdentID ID = IdentIDPair.second;
+ assert(II && "NULL identifier in identifier table");
+ if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
+ Generator.insert(II, ID, Trait);
}
// Create the on-disk hash table in a buffer.
@@ -3478,7 +3264,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
uint32_t BucketOffset;
{
using namespace llvm::support;
- ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
endian::Writer<little>(Out).write<uint32_t>(0);
@@ -3496,7 +3281,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
RecordData Record;
Record.push_back(IDENTIFIER_TABLE);
Record.push_back(BucketOffset);
- Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
+ Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
}
// Write the offsets table for identifier IDs.
@@ -3517,38 +3302,13 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
Record.push_back(IdentifierOffsets.size());
Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS);
Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
- data(IdentifierOffsets));
+ bytes(IdentifierOffsets));
}
//===----------------------------------------------------------------------===//
// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//
-/// Determine the declaration that should be put into the name lookup table to
-/// represent the given declaration in this module. This is usually D itself,
-/// but if D was imported and merged into a local declaration, we want the most
-/// recent local declaration instead. The chosen declaration will be the most
-/// recent declaration in any module that imports this one.
-static NamedDecl *getDeclForLocalLookup(NamedDecl *D) {
- if (!D->isFromASTFile())
- return D;
-
- if (Decl *Redecl = D->getPreviousDecl()) {
- // For Redeclarable decls, a prior declaration might be local.
- for (; Redecl; Redecl = Redecl->getPreviousDecl())
- if (!Redecl->isFromASTFile())
- return cast<NamedDecl>(Redecl);
- } else if (Decl *First = D->getCanonicalDecl()) {
- // For Mergeable decls, the first decl might be local.
- if (!First->isFromASTFile())
- return cast<NamedDecl>(First);
- }
-
- // All declarations are imported. Our most recent declaration will also be
- // the most recent one in anyone who imports us.
- return D;
-}
-
namespace {
// Trait used for the on-disk hash table used in the method pool.
class ASTDeclContextNameLookupTrait {
@@ -3666,119 +3426,198 @@ public:
LE.write<uint16_t>(Lookup.size());
for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();
I != E; ++I)
- LE.write<uint32_t>(Writer.GetDeclRef(getDeclForLocalLookup(*I)));
+ LE.write<uint32_t>(
+ Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), *I)));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
} // end anonymous namespace
-template<typename Visitor>
-static void visitLocalLookupResults(const DeclContext *ConstDC,
- bool NeedToReconcileExternalVisibleStorage,
- Visitor AddLookupResult) {
+bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
+ DeclContext *DC) {
+ return Result.hasExternalDecls() && DC->NeedToReconcileExternalVisibleStorage;
+}
+
+bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
+ DeclContext *DC) {
+ for (auto *D : Result.getLookupResult())
+ if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile())
+ return false;
+
+ return true;
+}
+
+uint32_t
+ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
+ llvm::SmallVectorImpl<char> &LookupTable) {
+ assert(!ConstDC->HasLazyLocalLexicalLookups &&
+ !ConstDC->HasLazyExternalLexicalLookups &&
+ "must call buildLookups first");
+
// FIXME: We need to build the lookups table, which is logically const.
DeclContext *DC = const_cast<DeclContext*>(ConstDC);
assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");
- SmallVector<DeclarationName, 16> ExternalNames;
+ // Create the on-disk hash table representation.
+ llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait>
+ Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // The first step is to collect the declaration names which we need to
+ // serialize into the name lookup table, and to collect them in a stable
+ // order.
+ SmallVector<DeclarationName, 16> Names;
+
+ // We also build up small sets of the constructor and conversion function
+ // names which are visible.
+ llvm::SmallSet<DeclarationName, 8> ConstructorNameSet, ConversionNameSet;
+
for (auto &Lookup : *DC->buildLookup()) {
- if (Lookup.second.hasExternalDecls() ||
- NeedToReconcileExternalVisibleStorage) {
- // We don't know for sure what declarations are found by this name,
- // because the external source might have a different set from the set
- // that are in the lookup map, and we can't update it now without
- // risking invalidating our lookup iterator. So add it to a queue to
- // deal with later.
- ExternalNames.push_back(Lookup.first);
+ auto &Name = Lookup.first;
+ auto &Result = Lookup.second;
+
+ // If there are no local declarations in our lookup result, we don't
+ // need to write an entry for the name at all unless we're rewriting
+ // the decl context. If we can't write out a lookup set without
+ // performing more deserialization, just skip this entry.
+ if (isLookupResultExternal(Result, DC) && !isRewritten(cast<Decl>(DC)) &&
+ isLookupResultEntirelyExternal(Result, DC))
continue;
- }
- AddLookupResult(Lookup.first, Lookup.second.getLookupResult());
- }
+ // We also skip empty results. If any of the results could be external and
+ // the currently available results are empty, then all of the results are
+ // external and we skip it above. So the only way we get here with an empty
+ // results is when no results could have been external *and* we have
+ // external results.
+ //
+ // FIXME: While we might want to start emitting on-disk entries for negative
+ // lookups into a decl context as an optimization, today we *have* to skip
+ // them because there are names with empty lookup results in decl contexts
+ // which we can't emit in any stable ordering: we lookup constructors and
+ // conversion functions in the enclosing namespace scope creating empty
+ // results for them. This in almost certainly a bug in Clang's name lookup,
+ // but that is likely to be hard or impossible to fix and so we tolerate it
+ // here by omitting lookups with empty results.
+ if (Lookup.second.getLookupResult().empty())
+ continue;
- // Add the names we needed to defer. Note, this shouldn't add any new decls
- // to the list we need to serialize: any new declarations we find here should
- // be imported from an external source.
- // FIXME: What if the external source isn't an ASTReader?
- for (const auto &Name : ExternalNames)
- AddLookupResult(Name, DC->lookup(Name));
-}
-
-void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) {
- if (UpdatedDeclContexts.insert(DC).second && WritingAST) {
- // Ensure we emit all the visible declarations.
- visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage,
- [&](DeclarationName Name,
- DeclContext::lookup_const_result Result) {
- for (auto *Decl : Result)
- GetDeclRef(getDeclForLocalLookup(Decl));
- });
+ switch (Lookup.first.getNameKind()) {
+ default:
+ Names.push_back(Lookup.first);
+ break;
+
+ case DeclarationName::CXXConstructorName:
+ assert(isa<CXXRecordDecl>(DC) &&
+ "Cannot have a constructor name outside of a class!");
+ ConstructorNameSet.insert(Name);
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ assert(isa<CXXRecordDecl>(DC) &&
+ "Cannot have a conversion function name outside of a class!");
+ ConversionNameSet.insert(Name);
+ break;
+ }
}
-}
-uint32_t
-ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
- llvm::SmallVectorImpl<char> &LookupTable) {
- assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+ // Sort the names into a stable order.
+ std::sort(Names.begin(), Names.end());
+
+ if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
+ // We need to establish an ordering of constructor and conversion function
+ // names, and they don't have an intrinsic ordering.
+
+ // First we try the easy case by forming the current context's constructor
+ // name and adding that name first. This is a very useful optimization to
+ // avoid walking the lexical declarations in many cases, and it also
+ // handles the only case where a constructor name can come from some other
+ // lexical context -- when that name is an implicit constructor merged from
+ // another declaration in the redecl chain. Any non-implicit constructor or
+ // conversion function which doesn't occur in all the lexical contexts
+ // would be an ODR violation.
+ auto ImplicitCtorName = Context->DeclarationNames.getCXXConstructorName(
+ Context->getCanonicalType(Context->getRecordType(D)));
+ if (ConstructorNameSet.erase(ImplicitCtorName))
+ Names.push_back(ImplicitCtorName);
+
+ // If we still have constructors or conversion functions, we walk all the
+ // names in the decl and add the constructors and conversion functions
+ // which are visible in the order they lexically occur within the context.
+ if (!ConstructorNameSet.empty() || !ConversionNameSet.empty())
+ for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls())
+ if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
+ auto Name = ChildND->getDeclName();
+ switch (Name.getNameKind()) {
+ default:
+ continue;
+
+ case DeclarationName::CXXConstructorName:
+ if (ConstructorNameSet.erase(Name))
+ Names.push_back(Name);
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ if (ConversionNameSet.erase(Name))
+ Names.push_back(Name);
+ break;
+ }
- llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait>
- Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
+ if (ConstructorNameSet.empty() && ConversionNameSet.empty())
+ break;
+ }
- // Create the on-disk hash table representation.
- DeclarationName ConstructorName;
- DeclarationName ConversionName;
+ assert(ConstructorNameSet.empty() && "Failed to find all of the visible "
+ "constructors by walking all the "
+ "lexical members of the context.");
+ assert(ConversionNameSet.empty() && "Failed to find all of the visible "
+ "conversion functions by walking all "
+ "the lexical members of the context.");
+ }
+
+ // Next we need to do a lookup with each name into this decl context to fully
+ // populate any results from external sources. We don't actually use the
+ // results of these lookups because we only want to use the results after all
+ // results have been loaded and the pointers into them will be stable.
+ for (auto &Name : Names)
+ DC->lookup(Name);
+
+ // Now we need to insert the results for each name into the hash table. For
+ // constructor names and conversion function names, we actually need to merge
+ // all of the results for them into one list of results each and insert
+ // those.
SmallVector<NamedDecl *, 8> ConstructorDecls;
- SmallVector<NamedDecl *, 4> ConversionDecls;
+ SmallVector<NamedDecl *, 8> ConversionDecls;
- visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage,
- [&](DeclarationName Name,
- DeclContext::lookup_result Result) {
- if (Result.empty())
- return;
+ // Now loop over the names, either inserting them or appending for the two
+ // special cases.
+ for (auto &Name : Names) {
+ DeclContext::lookup_result Result = DC->noload_lookup(Name);
- // Different DeclarationName values of certain kinds are mapped to
- // identical serialized keys, because we don't want to use type
- // identifiers in the keys (since type ids are local to the module).
switch (Name.getNameKind()) {
+ default:
+ Generator.insert(Name, Result, Trait);
+ break;
+
case DeclarationName::CXXConstructorName:
- // There may be different CXXConstructorName DeclarationName values
- // in a DeclContext because a UsingDecl that inherits constructors
- // has the DeclarationName of the inherited constructors.
- if (!ConstructorName)
- ConstructorName = Name;
ConstructorDecls.append(Result.begin(), Result.end());
- return;
+ break;
case DeclarationName::CXXConversionFunctionName:
- if (!ConversionName)
- ConversionName = Name;
ConversionDecls.append(Result.begin(), Result.end());
- return;
-
- default:
break;
}
-
- Generator.insert(Name, Result, Trait);
- });
-
- // Add the constructors.
- if (!ConstructorDecls.empty()) {
- Generator.insert(ConstructorName,
- DeclContext::lookup_result(ConstructorDecls.begin(),
- ConstructorDecls.end()),
- Trait);
}
- // Add the conversion functions.
- if (!ConversionDecls.empty()) {
- Generator.insert(ConversionName,
- DeclContext::lookup_result(ConversionDecls.begin(),
- ConversionDecls.end()),
- Trait);
- }
+ // Handle our two special cases if we ended up having any. We arbitrarily use
+ // the first declaration's name here because the name itself isn't part of
+ // the key, only the kind of name is used.
+ if (!ConstructorDecls.empty())
+ Generator.insert(ConstructorDecls.front()->getDeclName(),
+ DeclContext::lookup_result(ConstructorDecls), Trait);
+ if (!ConversionDecls.empty())
+ Generator.insert(ConversionDecls.front()->getDeclName(),
+ DeclContext::lookup_result(ConversionDecls), Trait);
// Create the on-disk hash table in a buffer.
llvm::raw_svector_ostream Out(LookupTable);
@@ -3795,12 +3634,60 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
/// bitstream, or 0 if no block was written.
uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
DeclContext *DC) {
+ // If we imported a key declaration of this namespace, write the visible
+ // lookup results as an update record for it rather than including them
+ // on this declaration. We will only look at key declarations on reload.
+ if (isa<NamespaceDecl>(DC) && Chain &&
+ Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {
+ // Only do this once, for the first local declaration of the namespace.
+ for (NamespaceDecl *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;
+ Prev = Prev->getPreviousDecl())
+ if (!Prev->isFromASTFile())
+ return 0;
+
+ // Note that we need to emit an update record for the primary context.
+ UpdatedDeclContexts.insert(DC->getPrimaryContext());
+
+ // Make sure all visible decls are written. They will be recorded later. We
+ // do this using a side data structure so we can sort the names into
+ // a deterministic order.
+ StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup();
+ SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>
+ LookupResults;
+ if (Map) {
+ LookupResults.reserve(Map->size());
+ for (auto &Entry : *Map)
+ LookupResults.push_back(
+ std::make_pair(Entry.first, Entry.second.getLookupResult()));
+ }
+
+ std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
+ for (auto &NameAndResult : LookupResults) {
+ DeclarationName Name = NameAndResult.first;
+ DeclContext::lookup_result Result = NameAndResult.second;
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ // We have to work around a name lookup bug here where negative lookup
+ // results for these names get cached in namespace lookup tables (these
+ // names should never be looked up in a namespace).
+ assert(Result.empty() && "Cannot have a constructor or conversion "
+ "function name in a namespace!");
+ continue;
+ }
+
+ for (NamedDecl *ND : Result)
+ if (!ND->isFromASTFile())
+ GetDeclRef(ND);
+ }
+
+ return 0;
+ }
+
if (DC->getPrimaryContext() != DC)
return 0;
- // Since there is no name lookup into functions or methods, don't bother to
- // build a visible-declarations table for these entities.
- if (DC->isFunctionOrMethod())
+ // Skip contexts which don't support name lookup.
+ if (!DC->isLookupContext())
return 0;
// If not in C++, we perform name lookup for the translation unit via the
@@ -3827,7 +3714,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
Record.push_back(DECL_CONTEXT_VISIBLE);
Record.push_back(BucketOffset);
Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
- LookupTable.str());
+ LookupTable);
++NumVisibleDeclContexts;
return Offset;
}
@@ -3847,12 +3734,17 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
SmallString<4096> LookupTable;
uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
+ // If we're updating a namespace, select a key declaration as the key for the
+ // update record; those are the only ones that will be checked on reload.
+ if (isa<NamespaceDecl>(DC))
+ DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));
+
// Write the lookup table
RecordData Record;
Record.push_back(UPDATE_VISIBLE);
Record.push_back(getDeclID(cast<Decl>(DC)));
Record.push_back(BucketOffset);
- Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str());
+ Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);
}
/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
@@ -3879,11 +3771,17 @@ void ASTWriter::WriteRedeclarations() {
SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
- Decl *First = Redeclarations[I];
- assert(First->isFirstDecl() && "Not the first declaration?");
-
- Decl *MostRecent = First->getMostRecentDecl();
-
+ const Decl *Key = Redeclarations[I];
+ assert((Chain ? Chain->getKeyDeclaration(Key) == Key
+ : Key->isFirstDecl()) &&
+ "not the key declaration");
+
+ const Decl *First = Key->getCanonicalDecl();
+ const Decl *MostRecent = First->getMostRecentDecl();
+
+ assert((getDeclID(First) >= NUM_PREDEF_DECL_IDS || First == Key) &&
+ "should not have imported key decls for predefined decl");
+
// If we only have a single declaration, there is no point in storing
// a redeclaration chain.
if (First == MostRecent)
@@ -3892,46 +3790,34 @@ void ASTWriter::WriteRedeclarations() {
unsigned Offset = LocalRedeclChains.size();
unsigned Size = 0;
LocalRedeclChains.push_back(0); // Placeholder for the size.
-
+
// Collect the set of local redeclarations of this declaration.
- for (Decl *Prev = MostRecent; Prev != First;
+ for (const Decl *Prev = MostRecent; Prev;
Prev = Prev->getPreviousDecl()) {
- if (!Prev->isFromASTFile()) {
+ if (!Prev->isFromASTFile() && Prev != Key) {
AddDeclRef(Prev, LocalRedeclChains);
++Size;
}
}
- if (!First->isFromASTFile() && Chain) {
- Decl *FirstFromAST = MostRecent;
- for (Decl *Prev = MostRecent; Prev; Prev = Prev->getPreviousDecl()) {
- if (Prev->isFromASTFile())
- FirstFromAST = Prev;
- }
-
- // FIXME: Do we need to do this for the first declaration from each
- // redeclaration chain that was merged into this one?
- Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First));
- }
-
LocalRedeclChains[Offset] = Size;
-
+
// Reverse the set of local redeclarations, so that we store them in
// order (since we found them in reverse order).
std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end());
-
+
// Add the mapping from the first ID from the AST to the set of local
// declarations.
- LocalRedeclarationsInfo Info = { getDeclID(First), Offset };
+ LocalRedeclarationsInfo Info = { getDeclID(Key), Offset };
LocalRedeclsMap.push_back(Info);
-
+
assert(N == Redeclarations.size() &&
"Deserialized a declaration we shouldn't have");
}
-
+
if (LocalRedeclChains.empty())
return;
-
+
// Sort the local redeclarations map by the first declaration ID,
// since the reader will be performing binary searches on this information.
llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
@@ -4008,25 +3894,6 @@ void ASTWriter::WriteObjCCategories() {
Stream.EmitRecord(OBJC_CATEGORIES, Categories);
}
-void ASTWriter::WriteMergedDecls() {
- if (!Chain || Chain->MergedDecls.empty())
- return;
-
- RecordData Record;
- for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(),
- IEnd = Chain->MergedDecls.end();
- I != IEnd; ++I) {
- DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID()
- : GetDeclRef(I->first);
- assert(CanonID && "Merged declaration not known?");
-
- Record.push_back(CanonID);
- Record.push_back(I->second.size());
- Record.append(I->second.begin(), I->second.end());
- }
- Stream.EmitRecord(MERGED_DECLARATIONS, Record);
-}
-
void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap;
@@ -4034,11 +3901,10 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
return;
RecordData Record;
- for (Sema::LateParsedTemplateMapT::iterator It = LPTMap.begin(),
- ItEnd = LPTMap.end();
- It != ItEnd; ++It) {
- LateParsedTemplate *LPT = It->second;
- AddDeclRef(It->first, Record);
+ for (auto LPTMapEntry : LPTMap) {
+ const FunctionDecl *FD = LPTMapEntry.first;
+ LateParsedTemplate *LPT = LPTMapEntry.second;
+ AddDeclRef(FD, Record);
AddDeclRef(LPT->D, Record);
Record.push_back(LPT->Toks.size());
@@ -4175,7 +4041,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
NumLexicalDeclContexts(0), NumVisibleDeclContexts(0),
- NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0),
+ NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1),
+ TypeExtQualAbbrev(0),
TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0),
UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0),
@@ -4188,6 +4055,11 @@ ASTWriter::~ASTWriter() {
llvm::DeleteContainerSeconds(FileDeclIDs);
}
+const LangOptions &ASTWriter::getLangOpts() const {
+ assert(WritingAST && "can't determine lang opts when not writing AST");
+ return Context->getLangOpts();
+}
+
void ASTWriter::WriteAST(Sema &SemaRef,
const std::string &OutputFile,
Module *WritingModule, StringRef isysroot,
@@ -4241,64 +4113,27 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Preprocessor &PP = SemaRef.PP;
// Set up predefined declaration IDs.
- DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID;
- if (Context.ObjCIdDecl)
- DeclIDs[Context.ObjCIdDecl] = PREDEF_DECL_OBJC_ID_ID;
- if (Context.ObjCSelDecl)
- DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID;
- if (Context.ObjCClassDecl)
- DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID;
- if (Context.ObjCProtocolClassDecl)
- DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID;
- if (Context.Int128Decl)
- DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID;
- if (Context.UInt128Decl)
- DeclIDs[Context.UInt128Decl] = PREDEF_DECL_UNSIGNED_INT_128_ID;
- if (Context.ObjCInstanceTypeDecl)
- DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID;
- if (Context.BuiltinVaListDecl)
- DeclIDs[Context.getBuiltinVaListDecl()] = PREDEF_DECL_BUILTIN_VA_LIST_ID;
-
- if (!Chain) {
- // Make sure that we emit IdentifierInfos (and any attached
- // declarations) for builtins. We don't need to do this when we're
- // emitting chained PCH files, because all of the builtins will be
- // in the original PCH file.
- // FIXME: Modules won't like this at all.
- IdentifierTable &Table = PP.getIdentifierTable();
- SmallVector<const char *, 32> BuiltinNames;
- if (!Context.getLangOpts().NoBuiltin) {
- Context.BuiltinInfo.GetBuiltinNames(BuiltinNames);
+ auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
+ if (D) {
+ assert(D->isCanonicalDecl() && "predefined decl is not canonical");
+ DeclIDs[D] = ID;
+ if (D->getMostRecentDecl() != D)
+ Redeclarations.push_back(D);
}
- for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
- getIdentifierRef(&Table.get(BuiltinNames[I]));
- }
-
- // If there are any out-of-date identifiers, bring them up to date.
- if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) {
- // Find out-of-date identifiers.
- SmallVector<IdentifierInfo *, 4> OutOfDate;
- for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
- IDEnd = PP.getIdentifierTable().end();
- ID != IDEnd; ++ID) {
- if (ID->second->isOutOfDate())
- OutOfDate.push_back(ID->second);
- }
-
- // Update the out-of-date identifiers.
- for (unsigned I = 0, N = OutOfDate.size(); I != N; ++I) {
- ExtSource->updateOutOfDateIdentifier(*OutOfDate[I]);
- }
- }
-
- // If we saw any DeclContext updates before we started writing the AST file,
- // make sure all visible decls in those DeclContexts are written out.
- if (!UpdatedDeclContexts.empty()) {
- auto OldUpdatedDeclContexts = std::move(UpdatedDeclContexts);
- UpdatedDeclContexts.clear();
- for (auto *DC : OldUpdatedDeclContexts)
- AddUpdatedDeclContext(DC);
- }
+ };
+ RegisterPredefDecl(Context.getTranslationUnitDecl(),
+ PREDEF_DECL_TRANSLATION_UNIT_ID);
+ RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID);
+ RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID);
+ RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID);
+ RegisterPredefDecl(Context.ObjCProtocolClassDecl,
+ PREDEF_DECL_OBJC_PROTOCOL_ID);
+ RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID);
+ RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID);
+ RegisterPredefDecl(Context.ObjCInstanceTypeDecl,
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID);
+ RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);
+ RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
// Build a record containing all of the tentative definitions in this file, in
// TentativeDefinitions order. Generally, this record will be empty for
@@ -4322,31 +4157,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// entire table, since later PCH files in a PCH chain are only interested in
// the results at the end of the chain.
RecordData WeakUndeclaredIdentifiers;
- if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
- for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
- I = SemaRef.WeakUndeclaredIdentifiers.begin(),
- E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
- AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
- AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
- AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
- WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
- }
+ for (auto &WeakUndeclaredIdentifier : SemaRef.WeakUndeclaredIdentifiers) {
+ IdentifierInfo *II = WeakUndeclaredIdentifier.first;
+ WeakInfo &WI = WeakUndeclaredIdentifier.second;
+ AddIdentifierRef(II, WeakUndeclaredIdentifiers);
+ AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers);
+ AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers);
+ WeakUndeclaredIdentifiers.push_back(WI.getUsed());
}
- // Build a record containing all of the locally-scoped extern "C"
- // declarations in this header file. Generally, this record will be
- // empty.
- RecordData LocallyScopedExternCDecls;
- // FIXME: This is filling in the AST file in densemap order which is
- // nondeterminstic!
- for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
- TD = SemaRef.LocallyScopedExternCDecls.begin(),
- TDEnd = SemaRef.LocallyScopedExternCDecls.end();
- TD != TDEnd; ++TD) {
- if (!TD->second->isFromASTFile())
- AddDeclRef(TD->second, LocallyScopedExternCDecls);
- }
-
// Build a record containing all of the ext_vector declarations.
RecordData ExtVectorDecls;
AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls);
@@ -4366,10 +4185,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)
AddDeclRef(TD, UnusedLocalTypedefNameCandidates);
- // Build a record containing all of dynamic classes declarations.
- RecordData DynamicClasses;
- AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses);
-
// Build a record containing all of pending implicit instantiations.
RecordData PendingInstantiations;
for (std::deque<Sema::PendingImplicitInstantiation>::iterator
@@ -4414,6 +4229,20 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
AddSourceLocation(I->second, UndefinedButUsed);
}
+ // Build a record containing all delete-expressions that we would like to
+ // analyze later in AST.
+ RecordData DeleteExprsToAnalyze;
+
+ for (const auto &DeleteExprsInfo :
+ SemaRef.getMismatchingDeleteExpressions()) {
+ AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);
+ DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());
+ for (const auto &DeleteLoc : DeleteExprsInfo.second) {
+ AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);
+ DeleteExprsToAnalyze.push_back(DeleteLoc.second);
+ }
+ }
+
// Write the control block
WriteControlBlock(PP, Context, isysroot, OutputFile);
@@ -4443,7 +4272,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Record.clear();
Record.push_back(TU_UPDATE_LEXICAL);
Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
- data(NewGlobalDecls));
+ bytes(NewGlobalDecls));
// And a visible updates block for the translation unit.
Abv = new llvm::BitCodeAbbrev();
@@ -4453,6 +4282,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);
WriteDeclContextVisibleUpdate(TU);
+
+ // If we have any extern "C" names, write out a visible update for them.
+ if (Context.ExternCContext)
+ WriteDeclContextVisibleUpdate(Context.ExternCContext);
// If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block.
@@ -4485,16 +4318,21 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Make sure all decls associated with an identifier are registered for
// serialization.
+ llvm::SmallVector<const IdentifierInfo*, 256> IIs;
for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
IDEnd = PP.getIdentifierTable().end();
ID != IDEnd; ++ID) {
const IdentifierInfo *II = ID->second;
- if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) {
- for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
- DEnd = SemaRef.IdResolver.end();
- D != DEnd; ++D) {
- GetDeclRef(*D);
- }
+ if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
+ IIs.push_back(II);
+ }
+ // Sort the identifiers to visit based on their name.
+ std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ for (const IdentifierInfo *II : IIs) {
+ for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
+ DEnd = SemaRef.IdResolver.end();
+ D != DEnd; ++D) {
+ GetDeclRef(*D);
}
}
@@ -4601,6 +4439,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
if (!DeclUpdatesOffsetsRecord.empty())
Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
WriteCXXBaseSpecifiersOffsets();
+ WriteCXXCtorInitializersOffsets();
WriteFileDeclIDsMap();
WriteSourceManagerBlock(Context.getSourceManager(), PP);
@@ -4637,11 +4476,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
WeakUndeclaredIdentifiers);
- // Write the record containing locally-scoped extern "C" definitions.
- if (!LocallyScopedExternCDecls.empty())
- Stream.EmitRecord(LOCALLY_SCOPED_EXTERN_C_DECLS,
- LocallyScopedExternCDecls);
-
// Write the record containing ext_vector type names.
if (!ExtVectorDecls.empty())
Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);
@@ -4650,10 +4484,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
if (!VTableUses.empty())
Stream.EmitRecord(VTABLE_USES, VTableUses);
- // Write the record containing dynamic classes declarations.
- if (!DynamicClasses.empty())
- Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
-
// Write the record containing potentially unused local typedefs.
if (!UnusedLocalTypedefNameCandidates.empty())
Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
@@ -4682,7 +4512,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Write the undefined internal functions and variables, and inline functions.
if (!UndefinedButUsed.empty())
Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);
-
+
+ if (!DeleteExprsToAnalyze.empty())
+ Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);
+
// Write the visible updates to DeclContexts.
for (auto *DC : UpdatedDeclContexts)
WriteDeclContextVisibleUpdate(DC);
@@ -4720,7 +4553,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// FIXME: If the module has macros imported then later has declarations
// imported, this location won't be the right one as a location for the
// declaration imports.
- AddSourceLocation(Import.M->MacroVisibilityLoc, ImportedModules);
+ AddSourceLocation(PP.getModuleImportLoc(Import.M), ImportedModules);
}
Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);
@@ -4729,7 +4562,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
WriteDeclReplacementsBlock();
WriteRedeclarations();
- WriteMergedDecls();
WriteObjCCategories();
WriteLateParsedTemplates(SemaRef);
if(!WritingModule)
@@ -4784,7 +4616,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
- AddUpdatedDeclContext(RD->getPrimaryContext());
+ UpdatedDeclContexts.insert(RD->getPrimaryContext());
AddCXXDefinitionData(RD, Record);
Record.push_back(WriteDeclContextLexicalBlock(
*Context, const_cast<CXXRecordDecl *>(RD)));
@@ -4828,6 +4660,10 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
break;
}
+ case UPD_CXX_RESOLVED_DTOR_DELETE:
+ AddDeclRef(Update.getDecl(), Record);
+ break;
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
addExceptionSpec(
*this,
@@ -4846,10 +4682,19 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
case UPD_STATIC_LOCAL_NUMBER:
Record.push_back(Update.getNumber());
break;
+
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
AddSourceRange(D->getAttr<OMPThreadPrivateDeclAttr>()->getRange(),
Record);
break;
+
+ case UPD_DECL_EXPORTED:
+ Record.push_back(getSubmoduleID(Update.getModule()));
+ break;
+
+ case UPD_ADDED_ATTR_TO_RECORD:
+ WriteAttributes(llvm::makeArrayRef(Update.getAttr()), Record);
+ break;
}
}
@@ -4859,8 +4704,6 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
Record.push_back(Def->isInlined());
AddSourceLocation(Def->getInnerLocStart(), Record);
AddFunctionDefinition(Def, Record);
- if (auto *DD = dyn_cast<CXXDestructorDecl>(Def))
- Record.push_back(GetDeclRef(DD->getOperatorDelete()));
}
OffsetsRecord.push_back(GetDeclRef(D));
@@ -4868,11 +4711,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
Stream.EmitRecord(DECL_UPDATES, Record);
- // Flush any statements that were written as part of this update record.
- FlushStmts();
-
- // Flush C++ base specifiers, if there are any.
- FlushCXXBaseSpecifiers();
+ FlushPendingAfterDecl();
}
}
@@ -4953,8 +4792,7 @@ MacroID ASTWriter::getMacroID(MacroInfo *MI) {
}
uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {
- assert(IdentMacroDirectivesOffsetMap[Name] && "not set!");
- return IdentMacroDirectivesOffsetMap[Name];
+ return IdentMacroDirectivesOffsetMap.lookup(Name);
}
void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) {
@@ -4984,8 +4822,16 @@ void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record
AddDeclRef(Temp->getDestructor(), Record);
}
+void ASTWriter::AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits,
+ RecordDataImpl &Record) {
+ assert(!Inits.empty() && "Empty ctor initializer sets are not recorded");
+ CXXCtorInitializersToWrite.push_back(
+ QueuedCXXCtorInitializers(NextCXXCtorInitializersID, Inits));
+ Record.push_back(NextCXXCtorInitializersID++);
+}
+
void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
- CXXBaseSpecifier const *BasesEnd,
+ CXXBaseSpecifier const *BasesEnd,
RecordDataImpl &Record) {
assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded");
CXXBaseSpecifiersToWrite.push_back(
@@ -5060,46 +4906,40 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) {
Record.push_back(GetOrCreateTypeID(T));
}
-TypeID ASTWriter::GetOrCreateTypeID( QualType T) {
+TypeID ASTWriter::GetOrCreateTypeID(QualType T) {
assert(Context);
- return MakeTypeID(*Context, T,
- std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
-}
-
-TypeID ASTWriter::getTypeID(QualType T) const {
- assert(Context);
- return MakeTypeID(*Context, T,
- std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
-}
+ return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
-TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {
- if (T.isNull())
- return TypeIdx();
- assert(!T.getLocalFastQualifiers());
+ TypeIdx &Idx = TypeIdxs[T];
+ if (Idx.getIndex() == 0) {
+ if (DoneWritingDeclsAndTypes) {
+ assert(0 && "New type seen after serializing all the types to emit!");
+ return TypeIdx();
+ }
- TypeIdx &Idx = TypeIdxs[T];
- if (Idx.getIndex() == 0) {
- if (DoneWritingDeclsAndTypes) {
- assert(0 && "New type seen after serializing all the types to emit!");
- return TypeIdx();
+ // We haven't seen this type before. Assign it a new ID and put it
+ // into the queue of types to emit.
+ Idx = TypeIdx(NextTypeID++);
+ DeclTypesToEmit.push(T);
}
-
- // We haven't seen this type before. Assign it a new ID and put it
- // into the queue of types to emit.
- Idx = TypeIdx(NextTypeID++);
- DeclTypesToEmit.push(T);
- }
- return Idx;
+ return Idx;
+ });
}
-TypeIdx ASTWriter::getTypeIdx(QualType T) const {
- if (T.isNull())
- return TypeIdx();
- assert(!T.getLocalFastQualifiers());
+TypeID ASTWriter::getTypeID(QualType T) const {
+ assert(Context);
+ return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
- TypeIdxMap::const_iterator I = TypeIdxs.find(T);
- assert(I != TypeIdxs.end() && "Type not emitted!");
- return I->second;
+ TypeIdxMap::const_iterator I = TypeIdxs.find(T);
+ assert(I != TypeIdxs.end() && "Type not emitted!");
+ return I->second;
+ });
}
void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {
@@ -5234,13 +5074,10 @@ unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {
// already done so.
auto It = AnonymousDeclarationNumbers.find(D);
if (It == AnonymousDeclarationNumbers.end()) {
- unsigned Index = 0;
- for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) {
- auto *ND = dyn_cast<NamedDecl>(LexicalD);
- if (!ND || !needsAnonymousDeclarationNumber(ND))
- continue;
- AnonymousDeclarationNumbers[ND] = Index++;
- }
+ auto *DC = D->getLexicalDeclContext();
+ numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) {
+ AnonymousDeclarationNumbers[ND] = Number;
+ });
It = AnonymousDeclarationNumbers.find(D);
assert(It != AnonymousDeclarationNumbers.end() &&
@@ -5555,7 +5392,8 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
void ASTWriter::FlushCXXBaseSpecifiers() {
RecordData Record;
- for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) {
+ unsigned N = CXXBaseSpecifiersToWrite.size();
+ for (unsigned I = 0; I != N; ++I) {
Record.clear();
// Record the offset of this base-specifier set.
@@ -5579,6 +5417,8 @@ void ASTWriter::FlushCXXBaseSpecifiers() {
FlushStmts();
}
+ assert(N == CXXBaseSpecifiersToWrite.size() &&
+ "added more base specifiers while writing base specifiers");
CXXBaseSpecifiersToWrite.clear();
}
@@ -5620,6 +5460,36 @@ void ASTWriter::AddCXXCtorInitializers(
}
}
+void ASTWriter::FlushCXXCtorInitializers() {
+ RecordData Record;
+
+ unsigned N = CXXCtorInitializersToWrite.size();
+ (void)N; // Silence unused warning in non-assert builds.
+ for (auto &Init : CXXCtorInitializersToWrite) {
+ Record.clear();
+
+ // Record the offset of this mem-initializer list.
+ unsigned Index = Init.ID - 1;
+ if (Index == CXXCtorInitializersOffsets.size())
+ CXXCtorInitializersOffsets.push_back(Stream.GetCurrentBitNo());
+ else {
+ if (Index > CXXCtorInitializersOffsets.size())
+ CXXCtorInitializersOffsets.resize(Index + 1);
+ CXXCtorInitializersOffsets[Index] = Stream.GetCurrentBitNo();
+ }
+
+ AddCXXCtorInitializers(Init.Inits.data(), Init.Inits.size(), Record);
+ Stream.EmitRecord(serialization::DECL_CXX_CTOR_INITIALIZERS, Record);
+
+ // Flush any expressions that were written as part of the initializers.
+ FlushStmts();
+ }
+
+ assert(N == CXXCtorInitializersToWrite.size() &&
+ "added more ctor initializers while writing ctor initializers");
+ CXXCtorInitializersToWrite.clear();
+}
+
void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) {
auto &Data = D->data();
Record.push_back(Data.IsLambda);
@@ -5725,6 +5595,8 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) {
Chain = Reader;
+ // Note, this will get called multiple times, once one the reader starts up
+ // and again each time it's done reading a PCH or module.
FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls();
FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes();
FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers();
@@ -5772,7 +5644,7 @@ void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
}
void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID,
- MacroDefinition *MD) {
+ MacroDefinitionRecord *MD) {
assert(MacroDefinitions.find(MD) == MacroDefinitions.end());
MacroDefinitions[MD] = ID;
}
@@ -5809,7 +5681,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
assert(!WritingAST && "Already writing the AST!");
- AddUpdatedDeclContext(DC);
+ UpdatedDeclContexts.insert(DC);
UpdatingVisibleDecls.push_back(D);
}
@@ -5863,21 +5735,36 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
}
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
- assert(!WritingAST && "Already writing the AST!");
- FD = FD->getCanonicalDecl();
- if (!FD->isFromASTFile())
- return; // Not a function declared in PCH and defined outside.
-
- DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
+ assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
+ if (!Chain) return;
+ Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
+ // If we don't already know the exception specification for this redecl
+ // chain, add an update record for it.
+ if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)
+ ->getType()
+ ->castAs<FunctionProtoType>()
+ ->getExceptionSpecType()))
+ DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
+ });
}
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
assert(!WritingAST && "Already writing the AST!");
- FD = FD->getCanonicalDecl();
- if (!FD->isFromASTFile())
- return; // Not a function declared in PCH and defined outside.
+ if (!Chain) return;
+ Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
+ });
+}
- DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
+void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) {
+ assert(!WritingAST && "Already writing the AST!");
+ assert(Delete && "Not given an operator delete");
+ if (!Chain) return;
+ Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));
+ });
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
@@ -5894,8 +5781,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
if (!D->isFromASTFile())
return;
- DeclUpdates[D].push_back(
- DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
@@ -5951,3 +5837,17 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));
}
+
+void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
+ assert(!WritingAST && "Already writing the AST!");
+ assert(D->isHidden() && "expected a hidden declaration");
+ DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M));
+}
+
+void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
+ const RecordDecl *Record) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!Record->isFromASTFile())
+ return;
+ DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr));
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index c97c2d8..fd6708d 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -117,6 +117,7 @@ namespace clang {
// FIXME: Put in the same order is DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
void VisitObjCIvarDecl(ObjCIvarDecl *D);
@@ -131,13 +132,83 @@ namespace clang {
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+ /// Add an Objective-C type parameter list to the given record.
+ void AddObjCTypeParamList(ObjCTypeParamList *typeParams) {
+ // Empty type parameter list.
+ if (!typeParams) {
+ Record.push_back(0);
+ return;
+ }
+
+ Record.push_back(typeParams->size());
+ for (auto typeParam : *typeParams) {
+ Writer.AddDeclRef(typeParam, Record);
+ }
+ Writer.AddSourceLocation(typeParams->getLAngleLoc(), Record);
+ Writer.AddSourceLocation(typeParams->getRAngleLoc(), Record);
+ }
+
void AddFunctionDefinition(const FunctionDecl *FD) {
assert(FD->doesThisDeclarationHaveABody());
- if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
- Writer.AddCXXCtorInitializers(CD->CtorInitializers,
- CD->NumCtorInitializers, Record);
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ Record.push_back(CD->NumCtorInitializers);
+ if (CD->NumCtorInitializers)
+ Writer.AddCXXCtorInitializersRef(
+ llvm::makeArrayRef(CD->init_begin(), CD->init_end()), Record);
+ }
Writer.AddStmt(FD->getBody());
}
+
+ /// Get the specialization decl from an entry in the specialization list.
+ template <typename EntryType>
+ typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
+ getSpecializationDecl(EntryType &T) {
+ return RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::getDecl(&T);
+ }
+
+ /// Get the list of partial specializations from a template's common ptr.
+ template<typename T>
+ decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) {
+ return Common->PartialSpecializations;
+ }
+ ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) {
+ return None;
+ }
+
+ template<typename Decl>
+ void AddTemplateSpecializations(Decl *D) {
+ auto *Common = D->getCommonPtr();
+
+ // If we have any lazy specializations, and the external AST source is
+ // our chained AST reader, we can just write out the DeclIDs. Otherwise,
+ // we need to resolve them to actual declarations.
+ if (Writer.Chain != Writer.Context->getExternalSource() &&
+ Common->LazySpecializations) {
+ D->LoadLazySpecializations();
+ assert(!Common->LazySpecializations);
+ }
+
+ auto &Specializations = Common->Specializations;
+ auto &&PartialSpecializations = getPartialSpecializations(Common);
+ ArrayRef<DeclID> LazySpecializations;
+ if (auto *LS = Common->LazySpecializations)
+ LazySpecializations = ArrayRef<DeclID>(LS + 1, LS + 1 + LS[0]);
+
+ Record.push_back(Specializations.size() +
+ PartialSpecializations.size() +
+ LazySpecializations.size());
+ for (auto &Entry : Specializations) {
+ auto *D = getSpecializationDecl(Entry);
+ assert(D->isCanonicalDecl() && "non-canonical decl in set");
+ Writer.AddDeclRef(D, Record);
+ }
+ for (auto &Entry : PartialSpecializations) {
+ auto *D = getSpecializationDecl(Entry);
+ assert(D->isCanonicalDecl() && "non-canonical decl in set");
+ Writer.AddDeclRef(D, Record);
+ }
+ Record.append(LazySpecializations.begin(), LazySpecializations.end());
+ }
};
}
@@ -157,7 +228,7 @@ void ASTDeclWriter::Visit(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Record.push_back(FD->doesThisDeclarationHaveABody());
if (FD->doesThisDeclarationHaveABody())
- Writer.AddStmt(FD->getBody());
+ AddFunctionDefinition(FD);
}
}
@@ -183,12 +254,14 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
//
// This happens when we instantiate a class with a friend declaration or a
// function with a local extern declaration, for instance.
+ //
+ // FIXME: Can we handle this in AddedVisibleDecl instead?
if (D->isOutOfLine()) {
auto *DC = D->getDeclContext();
while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) {
if (!NS->isFromASTFile())
break;
- Writer.AddUpdatedDeclContext(NS->getPrimaryContext());
+ Writer.UpdatedDeclContexts.insert(NS->getPrimaryContext());
if (!NS->isInlineNamespace())
break;
DC = NS->getParent();
@@ -203,8 +276,9 @@ void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
VisitDecl(D);
Writer.AddDeclarationName(D->getDeclName(), Record);
- if (needsAnonymousDeclarationNumber(D))
- Record.push_back(Writer.getAnonymousDeclarationNumber(D));
+ Record.push_back(needsAnonymousDeclarationNumber(D)
+ ? Writer.getAnonymousDeclarationNumber(D)
+ : 0);
}
void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
@@ -487,7 +561,7 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// FIXME: stable encoding for @required/@optional
Record.push_back(D->getImplementationControl());
- // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
+ // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway/nullability
Record.push_back(D->getObjCDeclQualifier());
Record.push_back(D->hasRelatedResultType());
Writer.AddTypeRef(D->getReturnType(), Record);
@@ -507,6 +581,16 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Code = serialization::DECL_OBJC_METHOD;
}
+void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ VisitTypedefNameDecl(D);
+ Record.push_back(D->Variance);
+ Record.push_back(D->Index);
+ Writer.AddSourceLocation(D->VarianceLoc, Record);
+ Writer.AddSourceLocation(D->ColonLoc, Record);
+
+ Code = serialization::DECL_OBJC_TYPE_PARAM;
+}
+
void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getAtStartLoc(), Record);
@@ -518,14 +602,14 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
VisitRedeclarable(D);
VisitObjCContainerDecl(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+ AddObjCTypeParamList(D->TypeParamList);
Record.push_back(D->isThisDeclarationADefinition());
if (D->isThisDeclarationADefinition()) {
// Write the DefinitionData
ObjCInterfaceDecl::DefinitionData &Data = D->data();
- Writer.AddDeclRef(D->getSuperClass(), Record);
- Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
+ Writer.AddTypeSourceInfo(D->getSuperClassTInfo(), Record);
Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record);
Record.push_back(Data.HasDesignatedInitializers);
@@ -605,6 +689,7 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
Writer.AddDeclRef(D->getClassInterface(), Record);
+ AddObjCTypeParamList(D->TypeParamList);
Record.push_back(D->protocol_size());
for (const auto *I : D->protocols())
Writer.AddDeclRef(I, Record);
@@ -623,6 +708,7 @@ void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddSourceLocation(D->getLParenLoc(), Record);
+ Writer.AddTypeRef(D->getType(), Record);
Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
// FIXME: stable encoding
Record.push_back((unsigned)D->getPropertyAttributes());
@@ -658,8 +744,10 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
Record.push_back(D->hasNonZeroConstructors());
Record.push_back(D->hasDestructors());
- Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
- Record);
+ Record.push_back(D->NumIvarInitializers);
+ if (D->NumIvarInitializers)
+ Writer.AddCXXCtorInitializersRef(
+ llvm::makeArrayRef(D->init_begin(), D->init_end()), Record);
Code = serialization::DECL_OBJC_IMPLEMENTATION;
}
@@ -732,13 +820,15 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->getStorageClass());
Record.push_back(D->getTSCSpec());
Record.push_back(D->getInitStyle());
- Record.push_back(D->isExceptionVariable());
- Record.push_back(D->isNRVOVariable());
- Record.push_back(D->isCXXForRangeDecl());
- Record.push_back(D->isARCPseudoStrong());
- Record.push_back(D->isConstexpr());
- Record.push_back(D->isInitCapture());
- Record.push_back(D->isPreviousDeclInSameBlockScope());
+ if (!isa<ParmVarDecl>(D)) {
+ Record.push_back(D->isExceptionVariable());
+ Record.push_back(D->isNRVOVariable());
+ Record.push_back(D->isCXXForRangeDecl());
+ Record.push_back(D->isARCPseudoStrong());
+ Record.push_back(D->isConstexpr());
+ Record.push_back(D->isInitCapture());
+ Record.push_back(D->isPreviousDeclInSameBlockScope());
+ }
Record.push_back(D->getLinkageInternal());
if (D->getInit()) {
@@ -917,23 +1007,6 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
Code = serialization::DECL_NAMESPACE;
- if (Writer.hasChain() && !D->isOriginalNamespace() &&
- D->getOriginalNamespace()->isFromASTFile()) {
- NamespaceDecl *NS = D->getOriginalNamespace();
- Writer.AddUpdatedDeclContext(NS);
-
- // Make sure all visible decls are written. They will be recorded later.
- if (StoredDeclsMap *Map = NS->buildLookup()) {
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- DeclContext::lookup_result R = D->second.getLookupResult();
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I)
- Writer.GetDeclRef(*I);
- }
- }
- }
-
if (Writer.hasChain() && D->isAnonymousNamespace() &&
D == D->getMostRecentDecl()) {
// This is a most recent reopening of the anonymous namespace. If its parent
@@ -1067,8 +1140,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
Writer.AddDeclRef(D->getInheritedConstructor(), Record);
Record.push_back(D->IsExplicitSpecified);
- Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers,
- Record);
Code = serialization::DECL_CXX_CONSTRUCTOR;
}
@@ -1076,7 +1147,7 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- Writer.AddDeclRef(D->OperatorDelete, Record);
+ Writer.AddDeclRef(D->getOperatorDelete(), Record);
Code = serialization::DECL_CXX_DESTRUCTOR;
}
@@ -1171,24 +1242,8 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
- if (D->isFirstDecl()) {
- typedef llvm::FoldingSetVector<ClassTemplateSpecializationDecl> CTSDSetTy;
- CTSDSetTy &CTSDSet = D->getSpecializations();
- Record.push_back(CTSDSet.size());
- for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) {
- assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
- Writer.AddDeclRef(&*I, Record);
- }
-
- typedef llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>
- CTPSDSetTy;
- CTPSDSetTy &CTPSDSet = D->getPartialSpecializations();
- Record.push_back(CTPSDSet.size());
- for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) {
- assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
- Writer.AddDeclRef(&*I, Record);
- }
- }
+ if (D->isFirstDecl())
+ AddTemplateSpecializations(D);
Code = serialization::DECL_CLASS_TEMPLATE;
}
@@ -1246,26 +1301,8 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
- if (D->isFirstDecl()) {
- typedef llvm::FoldingSetVector<VarTemplateSpecializationDecl> VTSDSetTy;
- VTSDSetTy &VTSDSet = D->getSpecializations();
- Record.push_back(VTSDSet.size());
- for (VTSDSetTy::iterator I = VTSDSet.begin(), E = VTSDSet.end(); I != E;
- ++I) {
- assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
- Writer.AddDeclRef(&*I, Record);
- }
-
- typedef llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
- VTPSDSetTy;
- VTPSDSetTy &VTPSDSet = D->getPartialSpecializations();
- Record.push_back(VTPSDSet.size());
- for (VTPSDSetTy::iterator I = VTPSDSet.begin(), E = VTPSDSet.end(); I != E;
- ++I) {
- assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
- Writer.AddDeclRef(&*I, Record);
- }
- }
+ if (D->isFirstDecl())
+ AddTemplateSpecializations(D);
Code = serialization::DECL_VAR_TEMPLATE;
}
@@ -1330,19 +1367,8 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
- if (D->isFirstDecl()) {
- // This FunctionTemplateDecl owns the CommonPtr; write it.
-
- // Write the function specialization declarations.
- Record.push_back(D->getSpecializations().size());
- for (llvm::FoldingSetVector<FunctionTemplateSpecializationInfo>::iterator
- I = D->getSpecializations().begin(),
- E = D->getSpecializations().end() ; I != E; ++I) {
- assert(I->Function->isCanonicalDecl() &&
- "Expected only canonical decls in set");
- Writer.AddDeclRef(I->Function, Record);
- }
- }
+ if (D->isFirstDecl())
+ AddTemplateSpecializations(D);
Code = serialization::DECL_FUNCTION_TEMPLATE;
}
@@ -1350,8 +1376,12 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
VisitTypeDecl(D);
Record.push_back(D->wasDeclaredWithTypename());
- Record.push_back(D->defaultArgumentWasInherited());
- Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
+
+ bool OwnsDefaultArg = D->hasDefaultArgument() &&
+ !D->defaultArgumentWasInherited();
+ Record.push_back(OwnsDefaultArg);
+ if (OwnsDefaultArg)
+ Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
Code = serialization::DECL_TEMPLATE_TYPE_PARM;
}
@@ -1378,11 +1408,11 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
} else {
// Rest of NonTypeTemplateParmDecl.
Record.push_back(D->isParameterPack());
- Record.push_back(D->getDefaultArgument() != nullptr);
- if (D->getDefaultArgument()) {
+ bool OwnsDefaultArg = D->hasDefaultArgument() &&
+ !D->defaultArgumentWasInherited();
+ Record.push_back(OwnsDefaultArg);
+ if (OwnsDefaultArg)
Writer.AddStmt(D->getDefaultArgument());
- Record.push_back(D->defaultArgumentWasInherited());
- }
Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
}
}
@@ -1407,9 +1437,12 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
} else {
// Rest of TemplateTemplateParmDecl.
- Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
- Record.push_back(D->defaultArgumentWasInherited());
Record.push_back(D->isParameterPack());
+ bool OwnsDefaultArg = D->hasDefaultArgument() &&
+ !D->defaultArgumentWasInherited();
+ Record.push_back(OwnsDefaultArg);
+ if (OwnsDefaultArg)
+ Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM;
}
}
@@ -1445,28 +1478,62 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
Record.push_back(VisibleOffset);
}
+/// Determine whether D is the first declaration in its redeclaration chain that
+/// is not from an AST file.
+template <typename T>
+static bool isFirstLocalDecl(Redeclarable<T> *D) {
+ assert(D && !static_cast<T*>(D)->isFromASTFile());
+ do
+ D = D->getPreviousDecl();
+ while (D && static_cast<T*>(D)->isFromASTFile());
+ return !D;
+}
+
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
T *First = D->getFirstDecl();
- if (First->getMostRecentDecl() != First) {
+ T *MostRecent = First->getMostRecentDecl();
+ if (MostRecent != First) {
assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) &&
"Not considered redeclarable?");
-
- // There is more than one declaration of this entity, so we will need to
- // write a redeclaration chain.
+
Writer.AddDeclRef(First, Record);
- Writer.Redeclarations.insert(First);
+
+ // In a modules build, emit a list of all imported key declarations
+ // (excluding First, if it was imported), so that we can be sure that all
+ // redeclarations visible to this module are before D in the redecl chain.
+ unsigned I = Record.size();
+ Record.push_back(0);
+ if (Context.getLangOpts().Modules && Writer.Chain) {
+ if (isFirstLocalDecl(D)) {
+ Writer.Chain->forEachImportedKeyDecl(First, [&](const Decl *D) {
+ if (D != First)
+ Writer.AddDeclRef(D, Record);
+ });
+ Record[I] = Record.size() - I - 1;
+
+ // Write a redeclaration chain, attached to the first key decl.
+ Writer.Redeclarations.push_back(Writer.Chain->getKeyDeclaration(First));
+ }
+ } else if (D == First || D->getPreviousDecl()->isFromASTFile()) {
+ assert(isFirstLocalDecl(D) && "imported decl after local decl");
+
+ // Write a redeclaration chain attached to the first decl.
+ Writer.Redeclarations.push_back(First);
+ }
// Make sure that we serialize both the previous and the most-recent
// declarations, which (transitively) ensures that all declarations in the
// chain get serialized.
+ //
+ // FIXME: This is not correct; when we reach an imported declaration we
+ // won't emit its previous declaration.
(void)Writer.GetDeclRef(D->getPreviousDecl());
- (void)Writer.GetDeclRef(First->getMostRecentDecl());
+ (void)Writer.GetDeclRef(MostRecent);
} else {
// We use the sentinel value 0 to indicate an only declaration.
Record.push_back(0);
}
-
}
void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
@@ -1504,6 +1571,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
@@ -1536,6 +1604,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
@@ -1573,6 +1642,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1620,6 +1690,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1662,6 +1733,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
@@ -1671,13 +1743,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
Abv->Add(BitCodeAbbrevOp(0)); // getTSCSpec
Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
- Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
- Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable
- Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl
- Abv->Add(BitCodeAbbrevOp(0)); // isARCPseudoStrong
- Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr
- Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture
- Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope
Abv->Add(BitCodeAbbrevOp(0)); // Linkage
Abv->Add(BitCodeAbbrevOp(0)); // HasInit
Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo
@@ -1715,6 +1780,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
@@ -1743,6 +1809,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
@@ -1788,6 +1855,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// NamedDecl
Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier
+ Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
@@ -1948,9 +2016,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
// Determine the ID for this declaration.
serialization::DeclID ID;
- if (D->isFromASTFile())
+ if (D->isFromASTFile()) {
+ assert(isRewritten(D) && "should not be emitting imported decl");
ID = getDeclID(D);
- else {
+ } else {
serialization::DeclID &IDR = DeclIDs[D];
if (IDR == 0)
IDR = NextDeclID++;
@@ -2015,12 +2084,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
D->getDeclKindName() + "'");
Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
- // Flush any expressions that were written as part of this declaration.
- FlushStmts();
-
- // Flush C++ base specifiers, if there are any.
- FlushCXXBaseSpecifiers();
-
+ // Flush any expressions, base specifiers, and ctor initializers that
+ // were written as part of this declaration.
+ FlushPendingAfterDecl();
+
// Note declarations that should be deserialized eagerly so that we can add
// them to a record in the AST file later.
if (isRequiredDecl(D, Context))
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index e980ce7..cddefac 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -553,6 +553,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
Writer.AddDeclRef(E->getMemberDecl(), Record);
Writer.AddSourceLocation(E->getMemberLoc(), Record);
Record.push_back(E->isArrow());
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
Writer.AddDeclarationNameLoc(E->MemberDNLoc,
E->getMemberDecl()->getDeclName(), Record);
Code = serialization::EXPR_MEMBER;
@@ -737,6 +738,18 @@ void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
Code = serialization::EXPR_DESIGNATED_INIT;
}
+void ASTStmtWriter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getBase());
+ Writer.AddStmt(E->getUpdater());
+ Code = serialization::EXPR_DESIGNATED_INIT_UPDATE;
+}
+
+void ASTStmtWriter::VisitNoInitExpr(NoInitExpr *E) {
+ VisitExpr(E);
+ Code = serialization::EXPR_NO_INIT;
+}
+
void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
@@ -1744,6 +1757,7 @@ void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
Record.push_back(C->getScheduleKind());
Writer->Writer.AddStmt(C->getChunkSize());
+ Writer->Writer.AddStmt(C->getHelperChunkSize());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record);
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
@@ -1797,6 +1811,14 @@ void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->private_copies())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->source_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
@@ -1814,15 +1836,32 @@ void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
- for (auto *VE : C->varlists())
+ for (auto *VE : C->varlists()) {
Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->inits()) {
+ Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->updates()) {
+ Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->finals()) {
+ Writer->Writer.AddStmt(VE);
+ }
Writer->Writer.AddStmt(C->getStep());
+ Writer->Writer.AddStmt(C->getCalcStep());
}
void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {
@@ -1839,6 +1878,12 @@ void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->source_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
@@ -1846,6 +1891,12 @@ void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *E : C->source_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Writer->Writer.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Writer->Writer.AddStmt(E);
}
void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
@@ -1855,6 +1906,16 @@ void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Record.push_back(C->getDependencyKind());
+ Writer->Writer.AddSourceLocation(C->getDependencyLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -1878,8 +1939,7 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
Writer.AddStmt(D->getLastIteration());
Writer.AddStmt(D->getCalcLastIteration());
Writer.AddStmt(D->getPreCond());
- Writer.AddStmt(D->getCond(/* SeparateIter */ false));
- Writer.AddStmt(D->getCond(/* SeparateIter */ true));
+ Writer.AddStmt(D->getCond());
Writer.AddStmt(D->getInit());
Writer.AddStmt(D->getInc());
if (isOpenMPWorksharingDirective(D->getDirectiveKind())) {
@@ -1990,6 +2050,9 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
Writer.AddStmt(D->getX());
Writer.AddStmt(D->getV());
Writer.AddStmt(D->getExpr());
+ Writer.AddStmt(D->getUpdateExpr());
+ Record.push_back(D->isXLHSInRHSPart() ? 1 : 0);
+ Record.push_back(D->isPostfixUpdate() ? 1 : 0);
Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE;
}
@@ -2018,6 +2081,12 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TASKGROUP_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
@@ -2038,6 +2107,21 @@ void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
Code = serialization::STMT_OMP_TEAMS_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPCancellationPointDirective(
+ OMPCancellationPointDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Record.push_back(D->getCancelRegion());
+ Code = serialization::STMT_OMP_CANCELLATION_POINT_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPCancelDirective(OMPCancelDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Record.push_back(D->getCancelRegion());
+ Code = serialization::STMT_OMP_CANCEL_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
index b5031fd..c461fe9 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
@@ -19,21 +19,18 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/Bitcode/BitstreamWriter.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
using namespace clang;
-PCHGenerator::PCHGenerator(const Preprocessor &PP,
- StringRef OutputFile,
- clang::Module *Module,
- StringRef isysroot,
- raw_ostream *OS, bool AllowASTWithErrors)
- : PP(PP), OutputFile(OutputFile), Module(Module),
- isysroot(isysroot.str()), Out(OS),
- SemaPtr(nullptr), Stream(Buffer), Writer(Stream),
- AllowASTWithErrors(AllowASTWithErrors),
- HasEmittedPCH(false) {
+PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
+ clang::Module *Module, StringRef isysroot,
+ std::shared_ptr<PCHBuffer> Buffer,
+ bool AllowASTWithErrors)
+ : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()),
+ SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data), Writer(Stream),
+ AllowASTWithErrors(AllowASTWithErrors) {
+ Buffer->IsComplete = false;
}
PCHGenerator::~PCHGenerator() {
@@ -47,21 +44,12 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
if (hasErrors && !AllowASTWithErrors)
return;
-
- // Emit the PCH file
+
+ // Emit the PCH file to the Buffer.
assert(SemaPtr && "No Sema?");
Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors);
- // Write the generated bitstream to "Out".
- Out->write((char *)&Buffer.front(), Buffer.size());
-
- // Make sure it hits disk now.
- Out->flush();
-
- // Free up some memory, in case the process is kept alive.
- Buffer.clear();
-
- HasEmittedPCH = true;
+ Buffer->IsComplete = true;
}
ASTMutationListener *PCHGenerator::GetASTMutationListener() {
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
index 4791388..2c7da3e 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "ASTReaderInternals.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Serialization/ASTBitCodes.h"
@@ -384,6 +385,7 @@ namespace {
/// \brief Builder that generates the global module index file.
class GlobalModuleIndexBuilder {
FileManager &FileMgr;
+ const PCHContainerOperations &PCHContainerOps;
/// \brief Mapping from files to module file information.
typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap;
@@ -416,7 +418,9 @@ namespace {
}
public:
- explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){}
+ explicit GlobalModuleIndexBuilder(
+ FileManager &FileMgr, const PCHContainerOperations &PCHContainerOps)
+ : FileMgr(FileMgr), PCHContainerOps(PCHContainerOps) {}
/// \brief Load the contents of the given module file into the builder.
///
@@ -501,8 +505,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Initialize the input stream
llvm::BitstreamReader InStreamFile;
- InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
- (const unsigned char *)(*Buffer)->getBufferEnd());
+ PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile);
llvm::BitstreamCursor InStream(InStreamFile);
// Sniff for the signature.
@@ -757,14 +760,16 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
Record.clear();
Record.push_back(IDENTIFIER_INDEX);
Record.push_back(BucketOffset);
- Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
+ Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
}
Stream.ExitBlock();
}
GlobalModuleIndex::ErrorCode
-GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) {
+GlobalModuleIndex::writeIndex(FileManager &FileMgr,
+ const PCHContainerOperations &PCHContainerOps,
+ StringRef Path) {
llvm::SmallString<128> IndexPath;
IndexPath += Path;
llvm::sys::path::append(IndexPath, IndexFileName);
@@ -787,8 +792,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) {
}
// The module index builder.
- GlobalModuleIndexBuilder Builder(FileMgr);
-
+ GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerOps);
+
// Load each of the module files.
std::error_code EC;
for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd;
@@ -841,12 +846,12 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) {
return EC_IOError;
// Remove the old index file. It isn't relevant any more.
- llvm::sys::fs::remove(IndexPath.str());
+ llvm::sys::fs::remove(IndexPath);
// Rename the newly-written index file to the proper name.
- if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) {
+ if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
// Rename failed; just remove the
- llvm::sys::fs::remove(IndexTmpPath.str());
+ llvm::sys::fs::remove(IndexTmpPath);
return EC_IOError;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
index 6c48a41..3b237d5 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
@@ -38,6 +38,7 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr),
LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0),
LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
+ LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr),
FileSortedDecls(nullptr), NumFileSortedDecls(0),
RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
index ac98ca0..03d8ed0 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
@@ -11,6 +11,7 @@
// modules for the ASTReader.
//
//===----------------------------------------------------------------------===//
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -58,8 +59,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
unsigned Generation,
off_t ExpectedSize, time_t ExpectedModTime,
ASTFileSignature ExpectedSignature,
- std::function<ASTFileSignature(llvm::BitstreamReader &)>
- ReadSignature,
+ ASTFileSignatureReader ReadSignature,
ModuleFile *&Module,
std::string &ErrorStr) {
Module = nullptr;
@@ -95,6 +95,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
New->File = Entry;
New->ImportLoc = ImportLoc;
Chain.push_back(New);
+ if (!ImportedBy)
+ Roots.push_back(New);
NewModule = true;
ModuleEntry = New;
@@ -135,10 +137,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
New->Buffer = std::move(*Buf);
}
-
- // Initialize the stream
- New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
- (const unsigned char *)New->Buffer->getBufferEnd());
+
+ // Initialize the stream.
+ PCHContainerOps.ExtractPCH(New->Buffer->getMemBufferRef(), New->StreamFile);
}
if (ExpectedSignature) {
@@ -156,7 +157,12 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// invalidate the file cache for Entry, and that is not safe if this
// module is *itself* up to date, but has an out-of-date importer.
Modules.erase(Entry);
+ assert(Chain.back() == ModuleEntry);
Chain.pop_back();
+ if (Roots.back() == ModuleEntry)
+ Roots.pop_back();
+ else
+ assert(ImportedBy);
delete ModuleEntry;
}
return OutOfDate;
@@ -187,12 +193,15 @@ void ModuleManager::removeModules(
// Collect the set of module file pointers that we'll be removing.
llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
+ auto IsVictim = [&](ModuleFile *MF) {
+ return victimSet.count(MF);
+ };
// Remove any references to the now-destroyed modules.
for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
- Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) {
- return victimSet.count(MF);
- });
+ Chain[i]->ImportedBy.remove_if(IsVictim);
}
+ Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
+ Roots.end());
// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = first; victim != last; ++victim) {
@@ -227,6 +236,15 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
InMemoryBuffers[Entry] = std::move(Buffer);
}
+bool ModuleManager::addKnownModuleFile(StringRef FileName) {
+ const FileEntry *File;
+ if (lookupModuleFile(FileName, 0, 0, File))
+ return true;
+ if (!Modules.count(File))
+ AdditionalKnownModuleFiles.insert(File);
+ return false;
+}
+
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
// Fast path: if we have a cached state, use it.
if (FirstVisitState) {
@@ -263,14 +281,18 @@ void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
}
void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
+ AdditionalKnownModuleFiles.remove(MF->File);
+
if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
return;
ModulesInCommonWithGlobalIndex.push_back(MF);
}
-ModuleManager::ModuleManager(FileManager &FileMgr)
- : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(nullptr) {}
+ModuleManager::ModuleManager(FileManager &FileMgr,
+ const PCHContainerOperations &PCHContainerOps)
+ : FileMgr(FileMgr), PCHContainerOps(PCHContainerOps), GlobalIndex(),
+ FirstVisitState(nullptr) {}
ModuleManager::~ModuleManager() {
for (unsigned i = 0, e = Chain.size(); i != e; ++i)
@@ -388,16 +410,38 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
returnVisitState(State);
}
+static void markVisitedDepthFirst(ModuleFile &M,
+ SmallVectorImpl<bool> &Visited) {
+ for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
+ IMEnd = M.Imports.end();
+ IM != IMEnd; ++IM) {
+ if (Visited[(*IM)->Index])
+ continue;
+ Visited[(*IM)->Index] = true;
+ if (!M.DirectlyImported)
+ markVisitedDepthFirst(**IM, Visited);
+ }
+}
+
/// \brief Perform a depth-first visit of the current module.
-static bool visitDepthFirst(ModuleFile &M,
- bool (*Visitor)(ModuleFile &M, bool Preorder,
- void *UserData),
- void *UserData,
- SmallVectorImpl<bool> &Visited) {
- // Preorder visitation
- if (Visitor(M, /*Preorder=*/true, UserData))
- return true;
-
+static bool visitDepthFirst(
+ ModuleFile &M,
+ ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
+ void *UserData),
+ bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData,
+ SmallVectorImpl<bool> &Visited) {
+ if (PreorderVisitor) {
+ switch (PreorderVisitor(M, UserData)) {
+ case ModuleManager::Abort:
+ return true;
+ case ModuleManager::SkipImports:
+ markVisitedDepthFirst(M, Visited);
+ return false;
+ case ModuleManager::Continue:
+ break;
+ }
+ }
+
// Visit children
for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
IMEnd = M.Imports.end();
@@ -406,24 +450,27 @@ static bool visitDepthFirst(ModuleFile &M,
continue;
Visited[(*IM)->Index] = true;
- if (visitDepthFirst(**IM, Visitor, UserData, Visited))
+ if (visitDepthFirst(**IM, PreorderVisitor, PostorderVisitor, UserData, Visited))
return true;
}
- // Postorder visitation
- return Visitor(M, /*Preorder=*/false, UserData);
+ if (PostorderVisitor)
+ return PostorderVisitor(M, UserData);
+
+ return false;
}
-void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder,
- void *UserData),
- void *UserData) {
+void ModuleManager::visitDepthFirst(
+ ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
+ void *UserData),
+ bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData) {
SmallVector<bool, 16> Visited(size(), false);
- for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
- if (Visited[Chain[I]->Index])
+ for (unsigned I = 0, N = Roots.size(); I != N; ++I) {
+ if (Visited[Roots[I]->Index])
continue;
- Visited[Chain[I]->Index] = true;
+ Visited[Roots[I]->Index] = true;
- if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
+ if (::visitDepthFirst(*Roots[I], PreorderVisitor, PostorderVisitor, UserData, Visited))
return;
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index cb5b010..557439b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -76,11 +76,10 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
// reference is outside the range.
// Generate a report for this bug.
- BugReport *report =
- new BugReport(*BT, BT->getDescription(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
report->addRange(LoadS->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index e462e2b..d8dc2aa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -207,7 +207,8 @@ void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
break;
}
- checkerContext.emitReport(new BugReport(*BT, os.str(), errorNode));
+ checkerContext.emitReport(
+ llvm::make_unique<BugReport>(*BT, os.str(), errorNode));
}
void RegionRawOffsetV2::dump() const {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 3fd5576..f763284 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -207,10 +207,10 @@ void NilArgChecker::generateBugReport(ExplodedNode *N,
if (!BT)
BT.reset(new APIMisuse(this, "nil argument"));
- BugReport *R = new BugReport(*BT, Msg, N);
+ auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
R->addRange(Range);
bugreporter::trackNullOrUndefValue(N, E, *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
@@ -516,9 +516,9 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
if (!BT)
BT.reset(new APIMisuse(this, "Bad use of CFNumberCreate"));
- BugReport *report = new BugReport(*BT, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(CE->getArg(2)->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
}
@@ -605,10 +605,10 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
else
llvm_unreachable("impossible case");
- BugReport *report = new BugReport(*BT, description, N);
+ auto report = llvm::make_unique<BugReport>(*BT, description, N);
report->addRange(Arg->getSourceRange());
bugreporter::trackNullOrUndefValue(N, Arg, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
}
@@ -666,9 +666,9 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
"of class '" << Class->getName()
<< "' and not the class directly";
- BugReport *report = new BugReport(*BT, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(msg.getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
}
@@ -819,9 +819,9 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
ArgTy.print(os, C.getLangOpts());
os << "'";
- BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
+ auto R = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
R->addRange(msg.getArgSourceRange(I));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
index 83a37c9..e945c38 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -35,7 +35,7 @@ void BoolAssignmentChecker::emitReport(ProgramStateRef state,
if (ExplodedNode *N = C.addTransition(state)) {
if (!BT)
BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
- C.emitReport(new BugReport(*BT, BT->getDescription(), N));
+ C.emitReport(llvm::make_unique<BugReport>(*BT, BT->getDescription(), N));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index e91a7e1..54b1241 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -245,11 +245,11 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
// Generate a report for this bug.
BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
- BugReport *report = new BugReport(*BT, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(S->getSourceRange());
bugreporter::trackNullOrUndefValue(N, S, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
return nullptr;
}
@@ -304,9 +304,9 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get());
// Generate a report for this bug.
- BugReport *report;
+ std::unique_ptr<BugReport> report;
if (warningMsg) {
- report = new BugReport(*BT, warningMsg, N);
+ report = llvm::make_unique<BugReport>(*BT, warningMsg, N);
} else {
assert(CurrentFunctionDescription);
assert(CurrentFunctionDescription[0] != '\0');
@@ -316,7 +316,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
os << toUppercase(CurrentFunctionDescription[0])
<< &CurrentFunctionDescription[1]
<< " accesses out-of-bound array element";
- report = new BugReport(*BT, os.str(), N);
+ report = llvm::make_unique<BugReport>(*BT, os.str(), N);
}
// FIXME: It would be nice to eventually make this diagnostic more clear,
@@ -324,7 +324,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
// reference is outside the range.
report->addRange(S->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
return nullptr;
}
@@ -534,13 +534,12 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
categories::UnixAPI, "Improper arguments"));
// Generate a report for this bug.
- BugReport *report =
- new BugReport(*BT_Overlap,
- "Arguments must not be overlapping buffers", N);
+ auto report = llvm::make_unique<BugReport>(
+ *BT_Overlap, "Arguments must not be overlapping buffers", N);
report->addRange(First->getSourceRange());
report->addRange(Second->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
@@ -603,8 +602,8 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
"be represented as a size_t";
// Generate a report for this bug.
- BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N);
- C.emitReport(report);
+ C.emitReport(
+ llvm::make_unique<BugReport>(*BT_AdditionOverflow, warning, N));
return nullptr;
}
@@ -721,10 +720,10 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
<< "', which is not a null-terminated string";
// Generate a report for this bug.
- BugReport *report = new BugReport(*BT_NotCString, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
report->addRange(Ex->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
return UndefinedVal();
@@ -785,11 +784,10 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
os << "not a null-terminated string";
// Generate a report for this bug.
- BugReport *report = new BugReport(*BT_NotCString,
- os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
report->addRange(Ex->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
return UndefinedVal();
@@ -1922,10 +1920,6 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
if (!evalFunction)
return false;
- // Make sure each function sets its own description.
- // (But don't bother in a release build.)
- assert(!(CurrentFunctionDescription = nullptr));
-
// Check and evaluate the call.
(this->*evalFunction)(C, CE);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
index abfb971d..3db1994 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -168,10 +168,9 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
}
void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E;
- ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index adb7a54..26423b7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -94,14 +94,14 @@ void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
if (!N)
return;
- BugReport *R = new BugReport(*BT, BT->getName(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
if (BadE) {
R->addRange(BadE->getSourceRange());
if (BadE->isGLValue())
BadE = bugreporter::getDerefExpr(BadE);
bugreporter::trackNullOrUndefValue(N, BadE, *R);
}
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
static StringRef describeUninitializedArgumentInCall(const CallEvent &Call,
@@ -164,12 +164,12 @@ bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C,
if (PSV.isUndef()) {
if (ExplodedNode *N = C.generateSink()) {
LazyInit_BT(BD, BT);
- BugReport *R = new BugReport(*BT, Message, N);
+ auto R = llvm::make_unique<BugReport>(*BT, Message, N);
R->addRange(ArgRange);
if (ArgEx) {
bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
}
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
return true;
}
@@ -199,11 +199,11 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
// Generate a report for this bug.
StringRef Desc =
describeUninitializedArgumentInCall(Call, IsFirstArgument);
- BugReport *R = new BugReport(*BT, Desc, N);
+ auto R = llvm::make_unique<BugReport>(*BT, Desc, N);
R->addRange(ArgRange);
if (ArgEx)
bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
return true;
}
@@ -281,12 +281,12 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
}
// Generate a report for this bug.
- BugReport *R = new BugReport(*BT, os.str(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, os.str(), N);
R->addRange(ArgRange);
// FIXME: enhance track back for uninitialized value for arbitrary
// memregions
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
return true;
}
@@ -342,9 +342,9 @@ void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
else
Desc = "Argument to 'delete' is uninitialized";
BugType *BT = BT_cxx_delete_undef.get();
- BugReport *R = new BugReport(*BT, Desc, N);
+ auto R = llvm::make_unique<BugReport>(*BT, Desc, N);
bugreporter::trackNullOrUndefValue(N, DE, *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
return;
}
}
@@ -400,8 +400,8 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
<< (Params == 1 ? "" : "s") << " is called with less ("
<< Call.getNumArgs() << ")";
- BugReport *R = new BugReport(*BT_call_few_args, os.str(), N);
- C.emitReport(R);
+ C.emitReport(
+ llvm::make_unique<BugReport>(*BT_call_few_args, os.str(), N));
}
}
@@ -461,14 +461,14 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
}
assert(BT && "Unknown message kind.");
- BugReport *R = new BugReport(*BT, BT->getName(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
const ObjCMessageExpr *ME = msg.getOriginExpr();
R->addRange(ME->getReceiverRange());
// FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
if (const Expr *ReceiverE = ME->getInstanceReceiver())
bugreporter::trackNullOrUndefValue(N, ReceiverE, *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
return;
} else {
@@ -512,13 +512,13 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
os << "' that will be garbage";
}
- BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_msg_ret, os.str(), N);
report->addRange(ME->getReceiverRange());
// FIXME: This won't track "self" in messages to super.
if (const Expr *receiver = ME->getInstanceReceiver()) {
bugreporter::trackNullOrUndefValue(N, receiver, *report);
}
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 3ba063d..0d683f9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -136,9 +136,9 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
"Cast a region whose size is not a multiple"
" of the destination type size."));
- BugReport *R = new BugReport(*BT, BT->getDescription(), errorNode);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), errorNode);
R->addRange(CE->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index d765315..ba3024d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -63,9 +63,9 @@ void CastToStructChecker::checkPreStmt(const CastExpr *CE,
"Casting a non-structure type to a structure type "
"and accessing a field can lead to memory access "
"errors or data corruption."));
- BugReport *R = new BugReport(*BT,BT->getDescription(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
R->addRange(CE->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 339af8f..12eb0bd 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -69,8 +69,8 @@ static bool scan_ivar_release(Stmt *S, ObjCIvarDecl *ID,
}
// Recurse to children.
- for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
- if (*I && scan_ivar_release(*I, ID, PD, Release, SelfII, Ctx))
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt && scan_ivar_release(SubStmt, ID, PD, Release, SelfII, Ctx))
return true;
return false;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 45768b2..e0c113c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -28,6 +28,7 @@ using namespace ento;
static bool isArc4RandomAvailable(const ASTContext &Ctx) {
const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
return T.getVendor() == llvm::Triple::Apple ||
+ T.getOS() == llvm::Triple::CloudABI ||
T.getOS() == llvm::Triple::FreeBSD ||
T.getOS() == llvm::Triple::NetBSD ||
T.getOS() == llvm::Triple::OpenBSD ||
@@ -108,9 +109,9 @@ public:
//===----------------------------------------------------------------------===//
void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
void WalkAST::VisitCallExpr(CallExpr *CE) {
@@ -161,11 +162,11 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
}
void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
- if (Stmt *child = *I) {
- if (CallExpr *CE = dyn_cast<CallExpr>(child))
+ for (Stmt *Child : S->children())
+ if (Child) {
+ if (CallExpr *CE = dyn_cast<CallExpr>(Child))
checkUncheckedReturnValue(CE);
- Visit(child);
+ Visit(Child);
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
index a61e658..81a2006 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -37,9 +37,9 @@ public:
}
void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
// CWE-467: Use of sizeof() on a Pointer Type
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index ba5b4fa..d1d6ac2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -295,7 +295,7 @@ def UnixAPIChecker : Checker<"API">,
HelpText<"Check calls to various UNIX/Posix functions">,
DescFile<"UnixAPIChecker.cpp">;
-def MallocPessimistic : Checker<"Malloc">,
+def MallocChecker: Checker<"Malloc">,
HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().">,
DescFile<"MallocChecker.cpp">;
@@ -315,10 +315,6 @@ def ChrootChecker : Checker<"Chroot">,
HelpText<"Check improper use of chroot">,
DescFile<"ChrootChecker.cpp">;
-def MallocOptimistic : Checker<"MallocWithAnnotations">,
- HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free(). Assumes that all user-defined functions which might free a pointer are annotated.">,
- DescFile<"MallocChecker.cpp">;
-
def PthreadLockChecker : Checker<"PthreadLock">,
HelpText<"Simple lock -> unlock checker">,
DescFile<"PthreadLockChecker.cpp">;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index ad41577..804e83c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -145,11 +145,10 @@ void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
BT_BreakJail.reset(new BuiltinBug(
this, "Break out of jail", "No call of chdir(\"/\") immediately "
"after chroot"));
- BugReport *R = new BugReport(*BT_BreakJail,
- BT_BreakJail->getDescription(), N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_BreakJail, BT_BreakJail->getDescription(), N));
}
-
+
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index c1ea767..f4be5b3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -142,7 +142,7 @@ public:
: cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents),
Escaped(escaped), currentBlock(nullptr) {}
- virtual ~DeadStoreObs() {}
+ ~DeadStoreObs() override {}
bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) {
if (Live.isLive(D))
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 4ee0223..2ba7ea4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -160,10 +160,8 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
}
os.flush();
- BugReport *report =
- new BugReport(*BT_null,
- buf.empty() ? BT_null->getDescription() : buf.str(),
- N);
+ auto report = llvm::make_unique<BugReport>(
+ *BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N);
bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S), *report);
@@ -171,7 +169,7 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
report->addRange(*I);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
@@ -183,11 +181,11 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
BT_undef.reset(
new BuiltinBug(this, "Dereference of undefined pointer value"));
- BugReport *report =
- new BugReport(*BT_undef, BT_undef->getDescription(), N);
+ auto report =
+ llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S),
*report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
index 0bcebf6..a71def2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
@@ -78,9 +78,9 @@ class DirectIvarAssignment :
void VisitBinaryOperator(const BinaryOperator *BO);
void VisitChildren(const Stmt *S) {
- for (Stmt::const_child_range I = S->children(); I; ++I)
- if (*I)
- this->Visit(*I);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ this->Visit(Child);
}
};
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index e060c36..79f9479b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -39,9 +39,9 @@ void DivZeroChecker::reportBug(const char *Msg,
if (!BT)
BT.reset(new BuiltinBug(this, "Division by zero"));
- BugReport *R = new BugReport(*BT, Msg, N);
+ auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
bugreporter::trackNullOrUndefValue(N, bugreporter::GetDenomExpr(N), *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index f36ec2c..7dc0a87 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -97,8 +97,8 @@ void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
- BugReport *R = new BugReport(*BT, getArgumentValueString(CE, C), N);
- C.emitReport(R);
+ C.emitReport(
+ llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
@@ -108,8 +108,7 @@ void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
- BugReport *R = new BugReport(*BT, "REACHABLE", N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(*BT, "REACHABLE", N));
}
void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
@@ -128,8 +127,8 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
- BugReport *R = new BugReport(*BT, getArgumentValueString(CE, C), N);
- C.emitReport(R);
+ C.emitReport(
+ llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 60bb036..48d6bd4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -57,9 +57,9 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
"Using a fixed address is not portable because that "
"address will probably not be valid in all "
"environments or platforms."));
- BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
R->addRange(B->getRHS()->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 08ba26a..2cf508f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -199,7 +199,7 @@ GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
const FunctionDecl *FDecl,
StringRef Name,
CheckerContext &C) {
- // TODO: Currently, we might loose precision here: we always mark a return
+ // TODO: Currently, we might lose precision here: we always mark a return
// value as tainted even if it's just a pointer, pointing to tainted data.
// Check for exact name match for functions without builtin substitutes.
@@ -642,9 +642,9 @@ bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
// Generate diagnostic.
if (ExplodedNode *N = C.addTransition()) {
initBugType();
- BugReport *report = new BugReport(*BT, Msg, N);
+ auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
report->addRange(E->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
return true;
}
return false;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
index b7549fd..d38d63c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
@@ -13,6 +13,8 @@
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_INTERCHECKERAPI_H
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_INTERCHECKERAPI_H
namespace clang {
+class CheckerManager;
+
namespace ento {
/// Register the checker which evaluates CString API calls.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index 1926600..3df5fa0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -167,9 +167,9 @@ class IvarInvalidationCheckerImpl {
void VisitObjCMessageExpr(const ObjCMessageExpr *ME);
void VisitChildren(const Stmt *S) {
- for (Stmt::const_child_range I = S->children(); I; ++I) {
- if (*I)
- this->Visit(*I);
+ for (const Stmt *Child : S->children()) {
+ if (Child)
+ this->Visit(Child);
if (CalledAnotherInvalidationMethod)
return;
}
@@ -336,7 +336,7 @@ const ObjCIvarDecl *IvarInvalidationCheckerImpl::findPropertyBackingIvar(
llvm::raw_svector_ostream os(PropNameWithUnderscore);
os << '_' << PropName;
}
- if (IvarName == PropNameWithUnderscore.str())
+ if (IvarName == PropNameWithUnderscore)
return Iv;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
index 0b7375a..4e3f9b7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -124,10 +124,9 @@ public:
const CheckerBase *checker)
: DeclWithIssue(declWithIssue), BR(br), Checker(checker) {}
void VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
- I != E; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
void VisitStmt(Stmt *S) { VisitChildren(S); }
void VisitDeclStmt(DeclStmt *DS);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 13ea4d3..7838901 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -103,9 +103,8 @@ private:
const ExplodedNode *getAllocationNode(const ExplodedNode *N, SymbolRef Sym,
CheckerContext &C) const;
- BugReport *generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
- ExplodedNode *N,
- CheckerContext &C) const;
+ std::unique_ptr<BugReport> generateAllocatedDataNotReleasedReport(
+ const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const;
/// Check if RetSym evaluates to an error value in the current state.
bool definitelyReturnedError(SymbolRef RetSym,
@@ -137,7 +136,7 @@ private:
public:
SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}
- virtual ~SecKeychainBugVisitor() {}
+ ~SecKeychainBugVisitor() override {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
@@ -269,11 +268,11 @@ void MacOSKeychainAPIChecker::
os << "Deallocator doesn't match the allocator: '"
<< FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
- BugReport *Report = new BugReport(*BT, os.str(), N);
+ auto Report = llvm::make_unique<BugReport>(*BT, os.str(), N);
Report->addVisitor(llvm::make_unique<SecKeychainBugVisitor>(AP.first));
Report->addRange(ArgExpr->getSourceRange());
- markInteresting(Report, AP);
- C.emitReport(Report);
+ markInteresting(Report.get(), AP);
+ C.emitReport(std::move(Report));
}
void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
@@ -292,7 +291,11 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
// If it is a call to an allocator function, it could be a double allocation.
idx = getTrackedFunctionIndex(funName, true);
if (idx != InvalidIdx) {
- const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
+ unsigned paramIdx = FunctionsToTrack[idx].Param;
+ if (CE->getNumArgs() <= paramIdx)
+ return;
+
+ const Expr *ArgExpr = CE->getArg(paramIdx);
if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C))
if (const AllocationState *AS = State->get<AllocatedData>(V)) {
if (!definitelyReturnedError(AS->Region, State, C.getSValBuilder())) {
@@ -310,11 +313,11 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
<< "the allocator: missing a call to '"
<< FunctionsToTrack[DIdx].Name
<< "'.";
- BugReport *Report = new BugReport(*BT, os.str(), N);
+ auto Report = llvm::make_unique<BugReport>(*BT, os.str(), N);
Report->addVisitor(llvm::make_unique<SecKeychainBugVisitor>(V));
Report->addRange(ArgExpr->getSourceRange());
Report->markInteresting(AS->Region);
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
}
return;
@@ -325,8 +328,12 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
if (idx == InvalidIdx)
return;
+ unsigned paramIdx = FunctionsToTrack[idx].Param;
+ if (CE->getNumArgs() <= paramIdx)
+ return;
+
// Check the argument to the deallocator.
- const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
+ const Expr *ArgExpr = CE->getArg(paramIdx);
SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext());
// Undef is reported by another checker.
@@ -362,12 +369,12 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
if (!N)
return;
initBugType();
- BugReport *Report = new BugReport(*BT,
- "Trying to free data which has not been allocated.", N);
+ auto Report = llvm::make_unique<BugReport>(
+ *BT, "Trying to free data which has not been allocated.", N);
Report->addRange(ArgExpr->getSourceRange());
if (AS)
Report->markInteresting(AS->Region);
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
return;
}
@@ -428,12 +435,12 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
if (!N)
return;
initBugType();
- BugReport *Report = new BugReport(*BT,
- "Only call free if a valid (non-NULL) buffer was returned.", N);
+ auto Report = llvm::make_unique<BugReport>(
+ *BT, "Only call free if a valid (non-NULL) buffer was returned.", N);
Report->addVisitor(llvm::make_unique<SecKeychainBugVisitor>(ArgSM));
Report->addRange(ArgExpr->getSourceRange());
Report->markInteresting(AS->Region);
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
return;
}
@@ -499,9 +506,11 @@ MacOSKeychainAPIChecker::getAllocationNode(const ExplodedNode *N,
while (N) {
if (!N->getState()->get<AllocatedData>(Sym))
break;
- // Allocation node, is the last node in the current context in which the
- // symbol was tracked.
- if (N->getLocationContext() == LeakContext)
+ // Allocation node, is the last node in the current or parent context in
+ // which the symbol was tracked.
+ const LocationContext *NContext = N->getLocationContext();
+ if (NContext == LeakContext ||
+ NContext->isParentOf(LeakContext))
AllocNode = N;
N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
@@ -509,10 +518,9 @@ MacOSKeychainAPIChecker::getAllocationNode(const ExplodedNode *N,
return AllocNode;
}
-BugReport *MacOSKeychainAPIChecker::
- generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
- ExplodedNode *N,
- CheckerContext &C) const {
+std::unique_ptr<BugReport>
+MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
+ const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const {
const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
initBugType();
SmallString<70> sbuf;
@@ -537,11 +545,12 @@ BugReport *MacOSKeychainAPIChecker::
C.getSourceManager(),
AllocNode->getLocationContext());
- BugReport *Report = new BugReport(*BT, os.str(), N, LocUsedForUniqueing,
- AllocNode->getLocationContext()->getDecl());
+ auto Report =
+ llvm::make_unique<BugReport>(*BT, os.str(), N, LocUsedForUniqueing,
+ AllocNode->getLocationContext()->getDecl());
Report->addVisitor(llvm::make_unique<SecKeychainBugVisitor>(AP.first));
- markInteresting(Report, AP);
+ markInteresting(Report.get(), AP);
return Report;
}
@@ -579,10 +588,8 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
// Generate the error reports.
- for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end();
- I != E; ++I) {
- C.emitReport(generateAllocatedDataNotReleasedReport(*I, N, C));
- }
+ for (const auto P : Errors)
+ C.emitReport(generateAllocatedDataNotReleasedReport(P, N, C));
// Generate the new, cleaned up state.
C.addTransition(State, N);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 13a401d..11ba609 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -92,9 +92,9 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
os << " Perhaps you intended to declare the variable as 'static'?";
- BugReport *report = new BugReport(*BT_dispatchOnce, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_dispatchOnce, os.str(), N);
report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index aee5a43..a9e0865 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -43,12 +43,15 @@ enum AllocationFamily {
AF_Malloc,
AF_CXXNew,
AF_CXXNewArray,
- AF_IfNameIndex
+ AF_IfNameIndex,
+ AF_Alloca
};
class RefState {
enum Kind { // Reference to allocated memory.
Allocated,
+ // Reference to zero-allocated memory.
+ AllocatedOfSizeZero,
// Reference to released/freed memory.
Released,
// The responsibility for freeing resources has transferred from
@@ -61,8 +64,8 @@ class RefState {
};
const Stmt *S;
- unsigned K : 2; // Kind enum, but stored as a bitfield.
- unsigned Family : 30; // Rest of 32-bit word, currently just an allocation
+ unsigned K : 3; // Kind enum, but stored as a bitfield.
+ unsigned Family : 29; // Rest of 32-bit word, currently just an allocation
// family.
RefState(Kind k, const Stmt *s, unsigned family)
@@ -71,6 +74,7 @@ class RefState {
}
public:
bool isAllocated() const { return K == Allocated; }
+ bool isAllocatedOfSizeZero() const { return K == AllocatedOfSizeZero; }
bool isReleased() const { return K == Released; }
bool isRelinquished() const { return K == Relinquished; }
bool isEscaped() const { return K == Escaped; }
@@ -86,6 +90,10 @@ public:
static RefState getAllocated(unsigned family, const Stmt *s) {
return RefState(Allocated, s, family);
}
+ static RefState getAllocatedOfSizeZero(const RefState *RS) {
+ return RefState(AllocatedOfSizeZero, RS->getStmt(),
+ RS->getAllocationFamily());
+ }
static RefState getReleased(unsigned family, const Stmt *s) {
return RefState(Released, s, family);
}
@@ -106,6 +114,7 @@ public:
switch (static_cast<Kind>(K)) {
#define CASE(ID) case ID: OS << #ID; break;
CASE(Allocated)
+ CASE(AllocatedOfSizeZero)
CASE(Released)
CASE(Relinquished)
CASE(Escaped)
@@ -160,16 +169,16 @@ class MallocChecker : public Checker<check::DeadSymbols,
{
public:
MallocChecker()
- : II_malloc(nullptr), II_free(nullptr), II_realloc(nullptr),
- II_calloc(nullptr), II_valloc(nullptr), II_reallocf(nullptr),
- II_strndup(nullptr), II_strdup(nullptr), II_kmalloc(nullptr),
- II_if_nameindex(nullptr), II_if_freenameindex(nullptr) {}
+ : II_alloca(nullptr), II_malloc(nullptr), II_free(nullptr),
+ II_realloc(nullptr), II_calloc(nullptr), II_valloc(nullptr),
+ II_reallocf(nullptr), II_strndup(nullptr), II_strdup(nullptr),
+ II_kmalloc(nullptr), II_if_nameindex(nullptr),
+ II_if_freenameindex(nullptr) {}
/// In pessimistic mode, the checker assumes that it does not know which
/// functions might free the memory.
enum CheckKind {
- CK_MallocPessimistic,
- CK_MallocOptimistic,
+ CK_MallocChecker,
CK_NewDeleteChecker,
CK_NewDeleteLeaksChecker,
CK_MismatchedDeallocatorChecker,
@@ -182,6 +191,8 @@ public:
MOK_Any
};
+ DefaultBool IsOptimistic;
+
DefaultBool ChecksEnabled[CK_NumCheckKinds];
CheckName CheckNames[CK_NumCheckKinds];
@@ -216,11 +227,14 @@ private:
mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
+ mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
- mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
- *II_valloc, *II_reallocf, *II_strndup, *II_strdup,
- *II_kmalloc, *II_if_nameindex, *II_if_freenameindex;
+ mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
+ mutable IdentifierInfo *II_alloca, *II_malloc, *II_free, *II_realloc,
+ *II_calloc, *II_valloc, *II_reallocf, *II_strndup,
+ *II_strdup, *II_kmalloc, *II_if_nameindex,
+ *II_if_freenameindex;
mutable Optional<uint64_t> KernelZeroFlagVal;
void initIdentifierInfo(ASTContext &C) const;
@@ -252,22 +266,24 @@ private:
MemoryOperationKind MemKind) const;
bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const;
///@}
+
+ /// \brief Perform a zero-allocation check.
+ ProgramStateRef ProcessZeroAllocation(CheckerContext &C, const Expr *E,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const;
+
ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
const CallExpr *CE,
- const OwnershipAttr* Att) const;
+ const OwnershipAttr* Att,
+ ProgramStateRef State) const;
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- const Expr *SizeEx, SVal Init,
- ProgramStateRef State,
- AllocationFamily Family = AF_Malloc) {
- return MallocMemAux(C, CE,
- State->getSVal(SizeEx, C.getLocationContext()),
- Init, State, Family);
- }
-
+ const Expr *SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family = AF_Malloc);
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- SVal SizeEx, SVal Init,
- ProgramStateRef State,
- AllocationFamily Family = AF_Malloc);
+ SVal SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family = AF_Malloc);
// Check if this malloc() for special flags. At present that means M_ZERO or
// __GFP_ZERO (in which case, treat it like calloc).
@@ -281,7 +297,8 @@ private:
AllocationFamily Family = AF_Malloc);
ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
- const OwnershipAttr* Att) const;
+ const OwnershipAttr* Att,
+ ProgramStateRef State) const;
ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
ProgramStateRef state, unsigned Num,
bool Hold,
@@ -295,14 +312,19 @@ private:
bool ReturnsNullOnFailure = false) const;
ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
- bool FreesMemOnFailure) const;
- static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
+ bool FreesMemOnFailure,
+ ProgramStateRef State) const;
+ static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
+ ProgramStateRef State);
///\brief Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
+ void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
+ const Stmt *S) const;
+
bool checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const;
/// Check if the function is known free memory, or if it is
@@ -330,15 +352,20 @@ private:
/// Tells if a given family/call/symbol is tracked by the current checker.
/// Sets CheckKind to the kind of the checker responsible for this
/// family/call/symbol.
- Optional<CheckKind> getCheckIfTracked(AllocationFamily Family) const;
+ Optional<CheckKind> getCheckIfTracked(AllocationFamily Family,
+ bool IsALeakCheck = false) const;
Optional<CheckKind> getCheckIfTracked(CheckerContext &C,
- const Stmt *AllocDeallocStmt) const;
- Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const;
+ const Stmt *AllocDeallocStmt,
+ bool IsALeakCheck = false) const;
+ Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
+ bool IsALeakCheck = false) const;
///@}
static bool SummarizeValue(raw_ostream &os, SVal V);
static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
const Expr *DeallocExpr) const;
+ void ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
+ SourceRange Range) const;
void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,
const Expr *DeallocExpr, const RefState *RS,
SymbolRef Sym, bool OwnershipTransferred) const;
@@ -352,6 +379,9 @@ private:
void ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const;
+ void ReportUseZeroAllocated(CheckerContext &C, SourceRange Range,
+ SymbolRef Sym) const;
+
/// Find the location of the allocation for Sym on the path leading to the
/// exploded node N.
LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
@@ -384,7 +414,7 @@ private:
MallocBugVisitor(SymbolRef S, bool isLeak = false)
: Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
- virtual ~MallocBugVisitor() {}
+ ~MallocBugVisitor() override {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
@@ -396,7 +426,9 @@ private:
const Stmt *Stmt) {
// Did not track -> allocated. Other state (released) -> allocated.
return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
- (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
+ (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
+ (!SPrev || !(SPrev->isAllocated() ||
+ SPrev->isAllocatedOfSizeZero())));
}
inline bool isReleased(const RefState *S, const RefState *SPrev,
@@ -422,7 +454,9 @@ private:
// check. If we have to handle more cases here, it might be cleaner just
// to track this extra bit in the state itself.
return ((!Stmt || !isa<CallExpr>(Stmt)) &&
- (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated()));
+ (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
+ (SPrev && !(SPrev->isAllocated() ||
+ SPrev->isAllocatedOfSizeZero())));
}
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
@@ -497,6 +531,7 @@ public:
void MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
if (II_malloc)
return;
+ II_alloca = &Ctx.Idents.get("alloca");
II_malloc = &Ctx.Idents.get("malloc");
II_free = &Ctx.Idents.get("free");
II_realloc = &Ctx.Idents.get("realloc");
@@ -517,6 +552,9 @@ bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
return true;
+ if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
+ return true;
+
if (isStandardNewDelete(FD, C))
return true;
@@ -560,12 +598,17 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,
if (FunI == II_if_nameindex)
return true;
}
+
+ if (Family == AF_Alloca && CheckAlloc) {
+ if (FunI == II_alloca)
+ return true;
+ }
}
if (Family != AF_Malloc)
return false;
- if (ChecksEnabled[CK_MallocOptimistic] && FD->hasAttrs()) {
+ if (IsOptimistic && FD->hasAttrs()) {
for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
@@ -712,6 +755,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
return;
if (CE->getNumArgs() < 3) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+ if (CE->getNumArgs() == 1)
+ State = ProcessZeroAllocation(C, CE, 0, State);
} else if (CE->getNumArgs() == 3) {
llvm::Optional<ProgramStateRef> MaybeState =
performKernelMalloc(CE, C, State);
@@ -731,31 +776,43 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
if (CE->getNumArgs() < 1)
return;
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+ State = ProcessZeroAllocation(C, CE, 0, State);
} else if (FunI == II_realloc) {
- State = ReallocMem(C, CE, false);
+ State = ReallocMem(C, CE, false, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_reallocf) {
- State = ReallocMem(C, CE, true);
+ State = ReallocMem(C, CE, true, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_calloc) {
- State = CallocMem(C, CE);
+ State = CallocMem(C, CE, State);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_free) {
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
} else if (FunI == II_strdup) {
State = MallocUpdateRefState(C, CE, State);
} else if (FunI == II_strndup) {
State = MallocUpdateRefState(C, CE, State);
- }
- else if (isStandardNewDelete(FD, C.getASTContext())) {
+ } else if (FunI == II_alloca) {
+ State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
+ AF_Alloca);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ } else if (isStandardNewDelete(FD, C.getASTContext())) {
// Process direct calls to operator new/new[]/delete/delete[] functions
// as distinct from new/new[]/delete/delete[] expressions that are
// processed by the checkPostStmt callbacks for CXXNewExpr and
// CXXDeleteExpr.
OverloadedOperatorKind K = FD->getOverloadedOperator();
- if (K == OO_New)
+ if (K == OO_New) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_CXXNew);
- else if (K == OO_Array_New)
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ }
+ else if (K == OO_Array_New) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_CXXNewArray);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ }
else if (K == OO_Delete || K == OO_Array_Delete)
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
else
@@ -770,19 +827,18 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
}
}
- if (ChecksEnabled[CK_MallocOptimistic] ||
- ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
+ if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
// Check all the attributes, if there are any.
// There can be multiple of these attributes.
if (FD->hasAttrs())
for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
switch (I->getOwnKind()) {
case OwnershipAttr::Returns:
- State = MallocMemReturnsAttr(C, CE, I);
+ State = MallocMemReturnsAttr(C, CE, I, State);
break;
case OwnershipAttr::Takes:
case OwnershipAttr::Holds:
- State = FreeMemAttr(C, CE, I);
+ State = FreeMemAttr(C, CE, I, State);
break;
}
}
@@ -790,6 +846,68 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
C.addTransition(State);
}
+// Performs a 0-sized allocations check.
+ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
+ const Expr *E,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
+ const Expr *Arg = nullptr;
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ Arg = CE->getArg(AllocationSizeArg);
+ }
+ else if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
+ if (NE->isArray())
+ Arg = NE->getArraySize();
+ else
+ return State;
+ }
+ else
+ llvm_unreachable("not a CallExpr or CXXNewExpr");
+
+ assert(Arg);
+
+ Optional<DefinedSVal> DefArgVal =
+ State->getSVal(Arg, C.getLocationContext()).getAs<DefinedSVal>();
+
+ if (!DefArgVal)
+ return State;
+
+ // Check if the allocation size is 0.
+ ProgramStateRef TrueState, FalseState;
+ SValBuilder &SvalBuilder = C.getSValBuilder();
+ DefinedSVal Zero =
+ SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
+
+ std::tie(TrueState, FalseState) =
+ State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
+
+ if (TrueState && !FalseState) {
+ SVal retVal = State->getSVal(E, C.getLocationContext());
+ SymbolRef Sym = retVal.getAsLocSymbol();
+ if (!Sym)
+ return State;
+
+ const RefState *RS = State->get<RegionState>(Sym);
+ if (!RS)
+ return State; // TODO: change to assert(RS); after realloc() will
+ // guarantee have a RegionState attached.
+
+ if (!RS->isAllocated())
+ return State;
+
+ return TrueState->set<RegionState>(Sym,
+ RefState::getAllocatedOfSizeZero(RS));
+ }
+
+ // Assume the value is non-zero going forward.
+ assert(FalseState);
+ return FalseState;
+}
+
static QualType getDeepPointeeType(QualType T) {
QualType Result = T, PointeeType = T->getPointeeType();
while (!PointeeType.isNull()) {
@@ -849,6 +967,7 @@ void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
// existing binding.
State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
: AF_CXXNew);
+ State = ProcessZeroAllocation(C, NE, 0, State);
C.addTransition(State);
}
@@ -919,15 +1038,31 @@ void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
ProgramStateRef
MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
- const OwnershipAttr *Att) const {
+ const OwnershipAttr *Att,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (Att->getModule() != II_malloc)
return nullptr;
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) {
- return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+ return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State);
}
- return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
+ return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
+}
+
+ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
+ const CallExpr *CE,
+ const Expr *SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family) {
+ if (!State)
+ return nullptr;
+
+ return MallocMemAux(C, CE, State->getSVal(SizeEx, C.getLocationContext()),
+ Init, State, Family);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
@@ -935,6 +1070,8 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
SVal Size, SVal Init,
ProgramStateRef State,
AllocationFamily Family) {
+ if (!State)
+ return nullptr;
// We expect the malloc functions to return a pointer.
if (!Loc::isLocType(CE->getType()))
@@ -976,6 +1113,9 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
const Expr *E,
ProgramStateRef State,
AllocationFamily Family) {
+ if (!State)
+ return nullptr;
+
// Get the return value.
SVal retVal = State->getSVal(E, C.getLocationContext());
@@ -992,11 +1132,14 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
const CallExpr *CE,
- const OwnershipAttr *Att) const {
+ const OwnershipAttr *Att,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (Att->getModule() != II_malloc)
return nullptr;
- ProgramStateRef State = C.getState();
bool ReleasedAllocated = false;
for (const auto &Arg : Att->args()) {
@@ -1011,15 +1154,18 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
const CallExpr *CE,
- ProgramStateRef state,
+ ProgramStateRef State,
unsigned Num,
bool Hold,
bool &ReleasedAllocated,
bool ReturnsNullOnFailure) const {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < (Num + 1))
return nullptr;
- return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
+ return FreeMemAux(C, CE->getArg(Num), CE, State, Hold,
ReleasedAllocated, ReturnsNullOnFailure);
}
@@ -1065,6 +1211,9 @@ AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,
if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
return AF_IfNameIndex;
+ if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
+ return AF_Alloca;
+
return AF_None;
}
@@ -1129,6 +1278,7 @@ void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C,
case AF_CXXNew: os << "'new'"; return;
case AF_CXXNewArray: os << "'new[]'"; return;
case AF_IfNameIndex: os << "'if_nameindex()'"; return;
+ case AF_Alloca:
case AF_None: llvm_unreachable("not a deallocation expression");
}
}
@@ -1140,7 +1290,8 @@ void MallocChecker::printExpectedDeallocName(raw_ostream &os,
case AF_CXXNew: os << "'delete'"; return;
case AF_CXXNewArray: os << "'delete[]'"; return;
case AF_IfNameIndex: os << "'if_freenameindex()'"; return;
- case AF_None: llvm_unreachable("suspicious AF_None argument");
+ case AF_Alloca:
+ case AF_None: llvm_unreachable("suspicious argument");
}
}
@@ -1152,6 +1303,9 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
bool &ReleasedAllocated,
bool ReturnsNullOnFailure) const {
+ if (!State)
+ return nullptr;
+
SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
if (!ArgVal.getAs<DefinedOrUnknownSVal>())
return nullptr;
@@ -1191,8 +1345,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
const MemSpaceRegion *MS = R->getMemorySpace();
- // Parameters, locals, statics, globals, and memory returned by alloca()
- // shouldn't be freed.
+ // Parameters, locals, statics, globals, and memory returned by
+ // __builtin_alloca() shouldn't be freed.
if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
// FIXME: at the time this code was written, malloc() regions were
// represented by conjured symbols, which are all in UnknownSpaceRegion.
@@ -1201,8 +1355,12 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
// Of course, free() can work on memory allocated outside the current
// function, so UnknownSpaceRegion is always a possibility.
// False negatives are better than false positives.
-
- ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
+
+ if (isa<AllocaRegion>(R))
+ ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
+ else
+ ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
+
return nullptr;
}
@@ -1218,6 +1376,12 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
if (RsBase) {
+ // Memory returned by alloca() shouldn't be freed.
+ if (RsBase->getAllocationFamily() == AF_Alloca) {
+ ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
+ return nullptr;
+ }
+
// Check for double free first.
if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
!didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
@@ -1227,7 +1391,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
// If the pointer is allocated or escaped, but we are now trying to free it,
// check that the call to free is proper.
- } else if (RsBase->isAllocated() || RsBase->isEscaped()) {
+ } else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
+ RsBase->isEscaped()) {
// Check if an expected deallocation function matches the real one.
bool DeallocMatchesAlloc =
@@ -1252,7 +1417,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
}
}
- ReleasedAllocated = (RsBase != nullptr) && RsBase->isAllocated();
+ ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
+ RsBase->isAllocatedOfSizeZero());
// Clean out the info on previous call to free return info.
State = State->remove<FreeReturnValue>(SymBase);
@@ -1281,21 +1447,26 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
}
Optional<MallocChecker::CheckKind>
-MallocChecker::getCheckIfTracked(AllocationFamily Family) const {
+MallocChecker::getCheckIfTracked(AllocationFamily Family,
+ bool IsALeakCheck) const {
switch (Family) {
case AF_Malloc:
+ case AF_Alloca:
case AF_IfNameIndex: {
- if (ChecksEnabled[CK_MallocOptimistic]) {
- return CK_MallocOptimistic;
- } else if (ChecksEnabled[CK_MallocPessimistic]) {
- return CK_MallocPessimistic;
- }
+ if (ChecksEnabled[CK_MallocChecker])
+ return CK_MallocChecker;
+
return Optional<MallocChecker::CheckKind>();
}
case AF_CXXNew:
case AF_CXXNewArray: {
- if (ChecksEnabled[CK_NewDeleteChecker]) {
- return CK_NewDeleteChecker;
+ if (IsALeakCheck) {
+ if (ChecksEnabled[CK_NewDeleteLeaksChecker])
+ return CK_NewDeleteLeaksChecker;
+ }
+ else {
+ if (ChecksEnabled[CK_NewDeleteChecker])
+ return CK_NewDeleteChecker;
}
return Optional<MallocChecker::CheckKind>();
}
@@ -1308,16 +1479,18 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family) const {
Optional<MallocChecker::CheckKind>
MallocChecker::getCheckIfTracked(CheckerContext &C,
- const Stmt *AllocDeallocStmt) const {
- return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt));
+ const Stmt *AllocDeallocStmt,
+ bool IsALeakCheck) const {
+ return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
+ IsALeakCheck);
}
Optional<MallocChecker::CheckKind>
-MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const {
-
+MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
+ bool IsALeakCheck) const {
const RefState *RS = C.getState()->get<RegionState>(Sym);
assert(RS);
- return getCheckIfTracked(RS->getAllocationFamily());
+ return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
}
bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
@@ -1411,8 +1584,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange Range,
const Expr *DeallocExpr) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
+ if (!ChecksEnabled[CK_MallocChecker] &&
!ChecksEnabled[CK_NewDeleteChecker])
return;
@@ -1433,28 +1605,50 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
MR = ER->getSuperRegion();
- if (MR && isa<AllocaRegion>(MR))
- os << "Memory allocated by alloca() should not be deallocated";
- else {
- os << "Argument to ";
- if (!printAllocDeallocName(os, C, DeallocExpr))
- os << "deallocator";
-
- os << " is ";
- bool Summarized = MR ? SummarizeRegion(os, MR)
- : SummarizeValue(os, ArgVal);
- if (Summarized)
- os << ", which is not memory allocated by ";
- else
- os << "not memory allocated by ";
+ os << "Argument to ";
+ if (!printAllocDeallocName(os, C, DeallocExpr))
+ os << "deallocator";
- printExpectedAllocName(os, C, DeallocExpr);
- }
+ os << " is ";
+ bool Summarized = MR ? SummarizeRegion(os, MR)
+ : SummarizeValue(os, ArgVal);
+ if (Summarized)
+ os << ", which is not memory allocated by ";
+ else
+ os << "not memory allocated by ";
+
+ printExpectedAllocName(os, C, DeallocExpr);
- BugReport *R = new BugReport(*BT_BadFree[*CheckKind], os.str(), N);
+ auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
R->markInteresting(MR);
R->addRange(Range);
- C.emitReport(R);
+ C.emitReport(std::move(R));
+ }
+}
+
+void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
+ SourceRange Range) const {
+
+ Optional<MallocChecker::CheckKind> CheckKind;
+
+ if (ChecksEnabled[CK_MallocChecker])
+ CheckKind = CK_MallocChecker;
+ else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
+ CheckKind = CK_MismatchedDeallocatorChecker;
+ else
+ return;
+
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_FreeAlloca[*CheckKind])
+ BT_FreeAlloca[*CheckKind].reset(
+ new BugType(CheckNames[*CheckKind], "Free alloca()", "Memory Error"));
+
+ auto R = llvm::make_unique<BugReport>(
+ *BT_FreeAlloca[*CheckKind],
+ "Memory allocated by alloca() should not be deallocated", N);
+ R->markInteresting(ArgVal.getAsRegion());
+ R->addRange(Range);
+ C.emitReport(std::move(R));
}
}
@@ -1505,11 +1699,11 @@ void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
os << ", not " << DeallocOs.str();
}
- BugReport *R = new BugReport(*BT_MismatchedDealloc, os.str(), N);
+ auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
@@ -1517,8 +1711,8 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
SourceRange Range, const Expr *DeallocExpr,
const Expr *AllocExpr) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
+
+ if (!ChecksEnabled[CK_MallocChecker] &&
!ChecksEnabled[CK_NewDeleteChecker])
return;
@@ -1564,17 +1758,16 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
else
os << "allocated memory";
- BugReport *R = new BugReport(*BT_OffsetFree[*CheckKind], os.str(), N);
+ auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
R->markInteresting(MR->getBaseRegion());
R->addRange(Range);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
+ if (!ChecksEnabled[CK_MallocChecker] &&
!ChecksEnabled[CK_NewDeleteChecker])
return;
@@ -1587,13 +1780,13 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
BT_UseFree[*CheckKind].reset(new BugType(
CheckNames[*CheckKind], "Use-after-free", "Memory Error"));
- BugReport *R = new BugReport(*BT_UseFree[*CheckKind],
- "Use of memory after it is freed", N);
+ auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
+ "Use of memory after it is freed", N);
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
@@ -1601,8 +1794,7 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
bool Released, SymbolRef Sym,
SymbolRef PrevSym) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
+ if (!ChecksEnabled[CK_MallocChecker] &&
!ChecksEnabled[CK_NewDeleteChecker])
return;
@@ -1615,17 +1807,17 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
BT_DoubleFree[*CheckKind].reset(
new BugType(CheckNames[*CheckKind], "Double free", "Memory Error"));
- BugReport *R =
- new BugReport(*BT_DoubleFree[*CheckKind],
- (Released ? "Attempt to free released memory"
- : "Attempt to free non-owned memory"),
- N);
+ auto R = llvm::make_unique<BugReport>(
+ *BT_DoubleFree[*CheckKind],
+ (Released ? "Attempt to free released memory"
+ : "Attempt to free non-owned memory"),
+ N);
R->addRange(Range);
R->markInteresting(Sym);
if (PrevSym)
R->markInteresting(PrevSym);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
@@ -1637,32 +1829,64 @@ void MallocChecker::ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const {
Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
if (!CheckKind.hasValue())
return;
- assert(*CheckKind == CK_NewDeleteChecker && "invalid check kind");
if (ExplodedNode *N = C.generateSink()) {
if (!BT_DoubleDelete)
BT_DoubleDelete.reset(new BugType(CheckNames[CK_NewDeleteChecker],
"Double delete", "Memory Error"));
- BugReport *R = new BugReport(*BT_DoubleDelete,
- "Attempt to delete released memory", N);
+ auto R = llvm::make_unique<BugReport>(
+ *BT_DoubleDelete, "Attempt to delete released memory", N);
R->markInteresting(Sym);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- C.emitReport(R);
+ C.emitReport(std::move(R));
+ }
+}
+
+void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
+ SourceRange Range,
+ SymbolRef Sym) const {
+
+ if (!ChecksEnabled[CK_MallocChecker] &&
+ !ChecksEnabled[CK_NewDeleteChecker])
+ return;
+
+ Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
+
+ if (!CheckKind.hasValue())
+ return;
+
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_UseZerroAllocated[*CheckKind])
+ BT_UseZerroAllocated[*CheckKind].reset(new BugType(
+ CheckNames[*CheckKind], "Use of zero allocated", "Memory Error"));
+
+ auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
+ "Use of zero-allocated memory", N);
+
+ R->addRange(Range);
+ if (Sym) {
+ R->markInteresting(Sym);
+ R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
+ }
+ C.emitReport(std::move(R));
}
}
ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
const CallExpr *CE,
- bool FreesOnFail) const {
+ bool FreesOnFail,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < 2)
return nullptr;
- ProgramStateRef state = C.getState();
const Expr *arg0Expr = CE->getArg(0);
const LocationContext *LCtx = C.getLocationContext();
- SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
+ SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
@@ -1670,7 +1894,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
SValBuilder &svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal PtrEQ =
- svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
+ svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
// Get the size argument. If there is no size arg then give up.
const Expr *Arg1 = CE->getArg(1);
@@ -1678,20 +1902,20 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
return nullptr;
// Get the value of the size argument.
- SVal Arg1ValG = state->getSVal(Arg1, LCtx);
+ SVal Arg1ValG = State->getSVal(Arg1, LCtx);
if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
// Compare the size argument to 0.
DefinedOrUnknownSVal SizeZero =
- svalBuilder.evalEQ(state, Arg1Val,
+ svalBuilder.evalEQ(State, Arg1Val,
svalBuilder.makeIntValWithPtrWidth(0, false));
ProgramStateRef StatePtrIsNull, StatePtrNotNull;
- std::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
+ std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
ProgramStateRef StateSizeIsZero, StateSizeNotZero;
- std::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
+ std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
// We only assume exceptional states if they are definitely true; if the
// state is under-constrained, assume regular realloc behavior.
bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
@@ -1711,7 +1935,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
assert(!PrtIsNull);
SymbolRef FromPtr = arg0Val.getAsSymbol();
- SVal RetVal = state->getSVal(CE, LCtx);
+ SVal RetVal = State->getSVal(CE, LCtx);
SymbolRef ToPtr = RetVal.getAsSymbol();
if (!FromPtr || !ToPtr)
return nullptr;
@@ -1731,7 +1955,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
// Default behavior.
if (ProgramStateRef stateFree =
- FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) {
+ FreeMemAux(C, CE, State, 0, false, ReleasedAllocated)) {
ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
UnknownVal(), stateFree);
@@ -1755,20 +1979,23 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
return nullptr;
}
-ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
+ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
+ ProgramStateRef State) {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < 2)
return nullptr;
- ProgramStateRef state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder();
const LocationContext *LCtx = C.getLocationContext();
- SVal count = state->getSVal(CE->getArg(0), LCtx);
- SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
- SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
+ SVal count = State->getSVal(CE->getArg(0), LCtx);
+ SVal elementSize = State->getSVal(CE->getArg(1), LCtx);
+ SVal TotalSize = svalBuilder.evalBinOp(State, BO_Mul, count, elementSize,
svalBuilder.getContext().getSizeType());
SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
- return MallocMemAux(C, CE, TotalSize, zeroVal, state);
+ return MallocMemAux(C, CE, TotalSize, zeroVal, State);
}
LeakInfo
@@ -1801,9 +2028,11 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
}
}
- // Allocation node, is the last node in the current context in which the
- // symbol was tracked.
- if (N->getLocationContext() == LeakContext)
+ // Allocation node, is the last node in the current or parent context in
+ // which the symbol was tracked.
+ const LocationContext *NContext = N->getLocationContext();
+ if (NContext == LeakContext ||
+ NContext->isParentOf(LeakContext))
AllocNode = N;
N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
@@ -1814,23 +2043,22 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
CheckerContext &C) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
+ if (!ChecksEnabled[CK_MallocChecker] &&
!ChecksEnabled[CK_NewDeleteLeaksChecker])
return;
const RefState *RS = C.getState()->get<RegionState>(Sym);
assert(RS && "cannot leak an untracked symbol");
AllocationFamily Family = RS->getAllocationFamily();
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
- if (!CheckKind.hasValue())
+
+ if (Family == AF_Alloca)
return;
- // Special case for new and new[]; these are controlled by a separate checker
- // flag so that they can be selectively disabled.
- if (Family == AF_CXXNew || Family == AF_CXXNewArray)
- if (!ChecksEnabled[CK_NewDeleteLeaksChecker])
- return;
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(Family, true);
+
+ if (!CheckKind.hasValue())
+ return;
assert(N);
if (!BT_Leak[*CheckKind]) {
@@ -1872,12 +2100,12 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
os << "Potential memory leak";
}
- BugReport *R =
- new BugReport(*BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
- AllocNode->getLocationContext()->getDecl());
+ auto R = llvm::make_unique<BugReport>(
+ *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
+ AllocNode->getLocationContext()->getDecl());
R->markInteresting(Sym);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym, true));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
@@ -1893,7 +2121,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
SmallVector<SymbolRef, 2> Errors;
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
if (SymReaper.isDead(I->first)) {
- if (I->second.isAllocated())
+ if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
Errors.push_back(I->first);
// Remove the dead symbol from the map.
RS = F.remove(RS, I->first);
@@ -1949,8 +2177,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
return;
ASTContext &Ctx = C.getASTContext();
- if ((ChecksEnabled[CK_MallocOptimistic] ||
- ChecksEnabled[CK_MallocPessimistic]) &&
+ if (ChecksEnabled[CK_MallocChecker] &&
(isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
isCMemFunction(FD, Ctx, AF_IfNameIndex,
MemoryOperationKind::MOK_Free)))
@@ -2062,6 +2289,15 @@ bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
return false;
}
+void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
+ const Stmt *S) const {
+ assert(Sym);
+ const RefState *RS = C.getState()->get<RegionState>(Sym);
+
+ if (RS && RS->isAllocatedOfSizeZero())
+ ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
+}
+
bool MallocChecker::checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const {
if (isReleased(Sym, C)) {
@@ -2075,8 +2311,10 @@ bool MallocChecker::checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const {
void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
CheckerContext &C) const {
SymbolRef Sym = l.getLocSymbolInBase();
- if (Sym)
+ if (Sym) {
checkUseAfterFree(Sym, C, S);
+ checkUseZeroAllocated(Sym, C, S);
+ }
}
// If a symbolic region is assumed to NULL (or another constant), stop tracking
@@ -2320,7 +2558,8 @@ ProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State,
continue;
if (const RefState *RS = State->get<RegionState>(sym)) {
- if (RS->isAllocated() && CheckRefState(RS)) {
+ if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
+ CheckRefState(RS)) {
State = State->remove<RegionState>(sym);
State = State->set<RegionState>(sym, RefState::getEscaped(RS));
}
@@ -2443,6 +2682,8 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
const RefState *RefS = State->get<RegionState>(I.getKey());
AllocationFamily Family = RefS->getAllocationFamily();
Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
+ if (!CheckKind.hasValue())
+ CheckKind = getCheckIfTracked(Family, true);
I.getKey()->dumpToStream(Out);
Out << " : ";
@@ -2457,6 +2698,8 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption(
+ "Optimistic", false, checker);
checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
mgr.getCurrentCheckName();
@@ -2470,11 +2713,12 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
void ento::register##name(CheckerManager &mgr) { \
registerCStringCheckerBasic(mgr); \
MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
+ "Optimistic", false, checker); \
checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
}
-REGISTER_CHECKER(MallocPessimistic)
-REGISTER_CHECKER(MallocOptimistic)
+REGISTER_CHECKER(MallocChecker)
REGISTER_CHECKER(NewDeleteChecker)
REGISTER_CHECKER(MismatchedDeallocatorChecker)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
index f38ce77..e913479 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -142,13 +142,13 @@ private:
}
}
}
- else if (isa<MemberExpr>(E)) {
+ else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
// No points-to analysis, just look at the member
- const Decl * EmeMD = dyn_cast<MemberExpr>(E)->getMemberDecl();
+ const Decl *EmeMD = ME->getMemberDecl();
while (i != e) {
--i;
- if (isa<MemberExpr>(i->variable)) {
- if (dyn_cast<MemberExpr>(i->variable)->getMemberDecl() == EmeMD)
+ if (const auto *ME_i = dyn_cast<MemberExpr>(i->variable)) {
+ if (ME_i->getMemberDecl() == EmeMD)
i = toScanFor.erase (i);
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
index 296aec6..fb07484 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -65,10 +65,9 @@ public:
}
void VisitChildren(const Stmt *S) {
- for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
- I!=E; ++I)
- if (const Stmt *child = *I)
- VisitChild(S, child);
+ for (const Stmt *Child : S->children())
+ if (Child)
+ VisitChild(S, Child);
}
TypeCallPair VisitCastExpr(const CastExpr *E) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index b180c03..d23708e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -68,10 +68,11 @@ void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
return;
}
- BugReport *Report = new BugReport(*BT, "Use -drain instead of -release when "
- "using NSAutoreleasePool and garbage collection", N);
+ auto Report = llvm::make_unique<BugReport>(
+ *BT, "Use -drain instead of -release when using NSAutoreleasePool and "
+ "garbage collection", N);
Report->addRange(msg.getSourceRange());
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 2be7f1d..c351c6e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -275,8 +275,7 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
CFBT.reset(new CFErrorDerefBug(this));
bug = CFBT.get();
}
- BugReport *report = new BugReport(*bug, os.str(), event.SinkNode);
- BR.emitReport(report);
+ BR.emitReport(llvm::make_unique<BugReport>(*bug, os.str(), event.SinkNode));
}
static bool IsNSError(QualType T, IdentifierInfo *II) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index cb2d46b..73f8087 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -36,10 +36,11 @@ public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
- BugReport *genReportNullAttrNonNull(const ExplodedNode *ErrorN,
- const Expr *ArgE) const;
- BugReport *genReportReferenceToNullPointer(const ExplodedNode *ErrorN,
- const Expr *ArgE) const;
+ std::unique_ptr<BugReport>
+ genReportNullAttrNonNull(const ExplodedNode *ErrorN, const Expr *ArgE) const;
+ std::unique_ptr<BugReport>
+ genReportReferenceToNullPointer(const ExplodedNode *ErrorN,
+ const Expr *ArgE) const;
};
} // end anonymous namespace
@@ -143,7 +144,7 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
// we cache out.
if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
- BugReport *R = nullptr;
+ std::unique_ptr<BugReport> R;
if (haveAttrNonNull)
R = genReportNullAttrNonNull(errorNode, ArgE);
else if (haveRefTypeParam)
@@ -153,7 +154,7 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
R->addRange(Call.getArgSourceRange(idx));
// Emit the bug report.
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
// Always return. Either we cached out or we just emitted an error.
@@ -171,8 +172,9 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
C.addTransition(state);
}
-BugReport *NonNullParamChecker::genReportNullAttrNonNull(
- const ExplodedNode *ErrorNode, const Expr *ArgE) const {
+std::unique_ptr<BugReport>
+NonNullParamChecker::genReportNullAttrNonNull(const ExplodedNode *ErrorNode,
+ const Expr *ArgE) const {
// Lazily allocate the BugType object if it hasn't already been
// created. Ownership is transferred to the BugReporter object once
// the BugReport is passed to 'EmitWarning'.
@@ -180,23 +182,22 @@ BugReport *NonNullParamChecker::genReportNullAttrNonNull(
BTAttrNonNull.reset(new BugType(
this, "Argument with 'nonnull' attribute passed null", "API"));
- BugReport *R = new BugReport(*BTAttrNonNull,
- "Null pointer passed as an argument to a 'nonnull' parameter",
- ErrorNode);
+ auto R = llvm::make_unique<BugReport>(
+ *BTAttrNonNull,
+ "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode);
if (ArgE)
bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
return R;
}
-BugReport *NonNullParamChecker::genReportReferenceToNullPointer(
- const ExplodedNode *ErrorNode, const Expr *ArgE) const {
+std::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
+ const ExplodedNode *ErrorNode, const Expr *ArgE) const {
if (!BTNullRefArg)
BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
- BugReport *R = new BugReport(*BTNullRefArg,
- "Forming reference to null pointer",
- ErrorNode);
+ auto R = llvm::make_unique<BugReport>(
+ *BTNullRefArg, "Forming reference to null pointer", ErrorNode);
if (ArgE) {
const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
if (!ArgEDeref)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index fbf2d73..a7b92b4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -47,10 +47,10 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
if (!BT_undef)
BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
"for @synchronized"));
- BugReport *report =
- new BugReport(*BT_undef, BT_undef->getDescription(), N);
+ auto report =
+ llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
bugreporter::trackNullOrUndefValue(N, Ex, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
return;
}
@@ -71,11 +71,11 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
BT_null.reset(new BuiltinBug(
this, "Nil value used as mutex for @synchronized() "
"(no synchronization will occur)"));
- BugReport *report =
- new BugReport(*BT_null, BT_null->getDescription(), N);
+ auto report =
+ llvm::make_unique<BugReport>(*BT_null, BT_null->getDescription(), N);
bugreporter::trackNullOrUndefValue(N, Ex, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
index e3fc611..224251b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -153,9 +153,9 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
}
void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 8e51154..53e1598 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -29,7 +29,8 @@ using namespace ento;
namespace {
class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>,
- check::PostStmt<CallExpr> > {
+ check::PostStmt<CallExpr>,
+ check::PointerEscape> {
mutable std::unique_ptr<BugType> BT;
inline void initBugType() const {
if (!BT)
@@ -52,6 +53,10 @@ public:
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+ ProgramStateRef checkPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const;
};
} // end anonymous namespace
@@ -110,7 +115,8 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
if (Name.equals("CFArrayGetValueAtIndex")) {
ProgramStateRef State = C.getState();
// Retrieve the size.
- // Find out if we saw this array symbol before and have information about it.
+ // Find out if we saw this array symbol before and have information about
+ // it.
const Expr *ArrayExpr = CE->getArg(0);
SymbolRef ArraySym = getArraySym(ArrayExpr, C);
if (!ArraySym)
@@ -137,14 +143,32 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
if (!N)
return;
initBugType();
- BugReport *R = new BugReport(*BT, "Index is out of bounds", N);
+ auto R = llvm::make_unique<BugReport>(*BT, "Index is out of bounds", N);
R->addRange(IdxExpr->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
return;
}
}
}
+ProgramStateRef
+ObjCContainersChecker::checkPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const {
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end();
+ I != E; ++I) {
+ SymbolRef Sym = *I;
+ // When a symbol for a mutable array escapes, we can't reason precisely
+ // about its size any more -- so remove it from the map.
+ // Note that we aren't notified here when a CFMutableArrayRef escapes as a
+ // CFArrayRef. This is because CFArrayRef is typedef'd as a pointer to a
+ // const-qualified type.
+ State = State->remove<ArraySizeMap>(Sym);
+ }
+ return State;
+}
/// Register checker.
void ento::registerObjCContainersChecker(CheckerManager &mgr) {
mgr.registerChecker<ObjCContainersChecker>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index a2cf8e1..016cb14 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -34,7 +34,6 @@ struct SelectorDescriptor {
const char *SelectorName;
unsigned ArgumentCount;
};
-}
//===----------------------------------------------------------------------===//
// FindSuperCallVisitor - Identify specific calls to the superclass.
@@ -63,7 +62,6 @@ private:
// ObjCSuperCallChecker
//===----------------------------------------------------------------------===//
-namespace {
class ObjCSuperCallChecker : public Checker<
check::ASTDecl<ObjCImplementationDecl> > {
public:
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 51bc7e6..93b0553 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -160,8 +160,7 @@ void ObjCSelfInitChecker::checkForInvalidSelf(const Expr *E, CheckerContext &C,
if (!BT)
BT.reset(new BugType(this, "Missing \"self = [(super or self) init...]\"",
categories::CoreFoundationObjectiveC));
- BugReport *report = new BugReport(*BT, errorStr, N);
- C.emitReport(report);
+ C.emitReport(llvm::make_unique<BugReport>(*BT, errorStr, N));
}
void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
index d3b1753..c6da37e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
@@ -57,8 +57,8 @@ static void Scan(IvarUsageMap& M, const Stmt *S) {
Scan(M, sub);
}
- for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I)
- Scan(M, *I);
+ for (const Stmt *SubStmt : S->children())
+ Scan(M, SubStmt);
}
static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl *D) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 00480e4..8063124 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -58,9 +58,9 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
"Pointer arithmetic done on non-array variables "
"means reliance on memory layout, which is "
"dangerous."));
- BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index fbb2628..cf1f88a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -66,9 +66,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
new BuiltinBug(this, "Pointer subtraction",
"Subtraction of two pointers that do not point to "
"the same memory chunk may cause incorrect result."));
- BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 1ede3a2..4209017 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -145,11 +145,10 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *report = new BugReport(*BT_doublelock,
- "This lock has already been acquired",
- N);
+ auto report = llvm::make_unique<BugReport>(
+ *BT_doublelock, "This lock has already been acquired", N);
report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
} else if (LState->isDestroyed()) {
reportUseDestroyedBug(C, CE);
@@ -208,11 +207,10 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *Report = new BugReport(*BT_doubleunlock,
- "This lock has already been unlocked",
- N);
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_doubleunlock, "This lock has already been unlocked", N);
Report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
return;
} else if (LState->isDestroyed()) {
reportUseDestroyedBug(C, CE);
@@ -232,13 +230,11 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *report = new BugReport(*BT_lor,
- "This was not the most recently "
- "acquired lock. Possible lock order "
- "reversal",
- N);
+ auto report = llvm::make_unique<BugReport>(
+ *BT_lor, "This was not the most recently acquired lock. Possible "
+ "lock order reversal", N);
report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
}
// Record that the lock was released.
@@ -279,9 +275,9 @@ void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *Report = new BugReport(*BT_destroylock, Message, N);
+ auto Report = llvm::make_unique<BugReport>(*BT_destroylock, Message, N);
Report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE,
@@ -314,9 +310,9 @@ void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *Report = new BugReport(*BT_initlock, Message, N);
+ auto Report = llvm::make_unique<BugReport>(*BT_initlock, Message, N);
Report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C,
@@ -327,11 +323,10 @@ void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C,
ExplodedNode *N = C.generateSink();
if (!N)
return;
- BugReport *Report = new BugReport(*BT_destroylock,
- "This lock has already been destroyed",
- N);
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_destroylock, "This lock has already been destroyed", N);
Report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void ento::registerPthreadLockChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 9a460ba..6ee87a5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -94,6 +94,16 @@ public:
ErrorReturnedNotOwned
};
+ /// Tracks how an object referenced by an ivar has been used.
+ ///
+ /// This accounts for us not knowing if an arbitrary ivar is supposed to be
+ /// stored at +0 or +1.
+ enum class IvarAccessHistory {
+ None,
+ AccessedDirectly,
+ ReleasedAfterDirectAccess
+ };
+
private:
/// The number of outstanding retains.
unsigned Cnt;
@@ -121,14 +131,16 @@ private:
/// This setting should not be propagated to state derived from this state.
/// Once we start deriving new states, it would be inconsistent to override
/// them.
- unsigned IsOverridable : 1;
+ unsigned RawIvarAccessHistory : 2;
RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t,
- bool Overridable = false)
+ IvarAccessHistory IvarAccess)
: Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
- RawObjectKind(static_cast<unsigned>(o)), IsOverridable(Overridable) {
+ RawObjectKind(static_cast<unsigned>(o)),
+ RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
assert(getKind() == k && "not enough bits for the kind");
assert(getObjKind() == o && "not enough bits for the object kind");
+ assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
}
public:
@@ -144,20 +156,24 @@ public:
void clearCounts() {
Cnt = 0;
ACnt = 0;
- IsOverridable = false;
}
void setCount(unsigned i) {
Cnt = i;
- IsOverridable = false;
}
void setAutoreleaseCount(unsigned i) {
ACnt = i;
- IsOverridable = false;
}
QualType getType() const { return T; }
- bool isOverridable() const { return IsOverridable; }
+ /// Returns what the analyzer knows about direct accesses to a particular
+ /// instance variable.
+ ///
+ /// If the object with this refcount wasn't originally from an Objective-C
+ /// ivar region, this should always return IvarAccessHistory::None.
+ IvarAccessHistory getIvarAccessHistory() const {
+ return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
+ }
bool isOwned() const {
return getKind() == Owned;
@@ -181,7 +197,7 @@ public:
/// Most commonly, this is an owned object with a retain count of +1.
static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
unsigned Count = 1) {
- return RefVal(Owned, o, Count, 0, t);
+ return RefVal(Owned, o, Count, 0, t, IvarAccessHistory::None);
}
/// Create a state for an object whose lifetime is not the responsibility of
@@ -190,47 +206,49 @@ public:
/// Most commonly, this is an unowned object with a retain count of +0.
static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
unsigned Count = 0) {
- return RefVal(NotOwned, o, Count, 0, t);
- }
-
- /// Create an "overridable" state for an unowned object at +0.
- ///
- /// An overridable state is one that provides a good approximation of the
- /// reference counting state now, but which may be discarded later if the
- /// checker sees the object being used in new ways.
- static RefVal makeOverridableNotOwned(RetEffect::ObjKind o, QualType t) {
- return RefVal(NotOwned, o, 0, 0, t, /*Overridable=*/true);
+ return RefVal(NotOwned, o, Count, 0, t, IvarAccessHistory::None);
}
RefVal operator-(size_t i) const {
return RefVal(getKind(), getObjKind(), getCount() - i,
- getAutoreleaseCount(), getType());
+ getAutoreleaseCount(), getType(), getIvarAccessHistory());
}
RefVal operator+(size_t i) const {
return RefVal(getKind(), getObjKind(), getCount() + i,
- getAutoreleaseCount(), getType());
+ getAutoreleaseCount(), getType(), getIvarAccessHistory());
}
RefVal operator^(Kind k) const {
return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
- getType());
+ getType(), getIvarAccessHistory());
}
RefVal autorelease() const {
return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
- getType());
+ getType(), getIvarAccessHistory());
+ }
+
+ RefVal withIvarAccess() const {
+ assert(getIvarAccessHistory() == IvarAccessHistory::None);
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
+ getType(), IvarAccessHistory::AccessedDirectly);
+ }
+ RefVal releaseViaIvar() const {
+ assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
+ getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
}
// Comparison, profiling, and pretty-printing.
bool hasSameState(const RefVal &X) const {
- return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt;
+ return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
+ getIvarAccessHistory() == X.getIvarAccessHistory();
}
bool operator==(const RefVal& X) const {
- return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind() &&
- IsOverridable == X.IsOverridable;
+ return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
}
void Profile(llvm::FoldingSetNodeID& ID) const {
@@ -239,7 +257,7 @@ public:
ID.AddInteger(Cnt);
ID.AddInteger(ACnt);
ID.AddInteger(RawObjectKind);
- ID.AddBoolean(IsOverridable);
+ ID.AddInteger(RawIvarAccessHistory);
}
void print(raw_ostream &Out) const;
@@ -249,9 +267,6 @@ void RefVal::print(raw_ostream &Out) const {
if (!T.isNull())
Out << "Tracked " << T.getAsString() << '/';
- if (isOverridable())
- Out << "(overridable) ";
-
switch (getKind()) {
default: llvm_unreachable("Invalid RefVal kind");
case Owned: {
@@ -323,8 +338,18 @@ void RefVal::print(raw_ostream &Out) const {
break;
}
+ switch (getIvarAccessHistory()) {
+ case IvarAccessHistory::None:
+ break;
+ case IvarAccessHistory::AccessedDirectly:
+ Out << " [direct ivar access]";
+ break;
+ case IvarAccessHistory::ReleasedAfterDirectAccess:
+ Out << " [released after direct ivar access]";
+ }
+
if (ACnt) {
- Out << " [ARC +" << ACnt << ']';
+ Out << " [autorelease -" << ACnt << ']';
}
}
} //end anonymous namespace
@@ -881,6 +906,8 @@ static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
case IncRef:
case IncRefMsg:
case MakeCollectable:
+ case UnretainedOutParameter:
+ case RetainedOutParameter:
case MayEscape:
case StopTracking:
case StopTrackingHard:
@@ -1310,7 +1337,18 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
if (pd->hasAttr<NSConsumedAttr>())
Template->addArg(AF, parm_idx, DecRefMsg);
else if (pd->hasAttr<CFConsumedAttr>())
- Template->addArg(AF, parm_idx, DecRef);
+ Template->addArg(AF, parm_idx, DecRef);
+ else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
+ QualType PointeeTy = pd->getType()->getPointeeType();
+ if (!PointeeTy.isNull())
+ if (coreFoundation::isCFObjectRef(PointeeTy))
+ Template->addArg(AF, parm_idx, RetainedOutParameter);
+ } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
+ QualType PointeeTy = pd->getType()->getPointeeType();
+ if (!PointeeTy.isNull())
+ if (coreFoundation::isCFObjectRef(PointeeTy))
+ Template->addArg(AF, parm_idx, UnretainedOutParameter);
+ }
}
QualType RetTy = FD->getReturnType();
@@ -1341,7 +1379,17 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
Template->addArg(AF, parm_idx, DecRefMsg);
else if (pd->hasAttr<CFConsumedAttr>()) {
Template->addArg(AF, parm_idx, DecRef);
- }
+ } else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
+ QualType PointeeTy = pd->getType()->getPointeeType();
+ if (!PointeeTy.isNull())
+ if (coreFoundation::isCFObjectRef(PointeeTy))
+ Template->addArg(AF, parm_idx, RetainedOutParameter);
+ } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
+ QualType PointeeTy = pd->getType()->getPointeeType();
+ if (!PointeeTy.isNull())
+ if (coreFoundation::isCFObjectRef(PointeeTy))
+ Template->addArg(AF, parm_idx, UnretainedOutParameter);
+ }
}
QualType RetTy = MD->getReturnType();
@@ -1763,12 +1811,11 @@ namespace {
addGCModeDescription(LOpts, GCEnabled);
}
- std::pair<ranges_iterator, ranges_iterator> getRanges() override {
+ llvm::iterator_range<ranges_iterator> getRanges() override {
const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType());
if (!BugTy.isLeak())
return BugReport::getRanges();
- else
- return std::make_pair(ranges_iterator(), ranges_iterator());
+ return llvm::make_range(ranges_iterator(), ranges_iterator());
}
};
@@ -1829,6 +1876,16 @@ static bool isNumericLiteralExpression(const Expr *E) {
isa<CXXBoolLiteralExpr>(E);
}
+/// Returns true if this stack frame is for an Objective-C method that is a
+/// property getter or setter whose body has been synthesized by the analyzer.
+static bool isSynthesizedAccessor(const StackFrameContext *SFC) {
+ auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
+ if (!Method || !Method->isPropertyAccessor())
+ return false;
+
+ return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
+}
+
PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
@@ -1859,6 +1916,11 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
if (!PrevT) {
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
+ if (isa<ObjCIvarRefExpr>(S) &&
+ isSynthesizedAccessor(LCtx->getCurrentStackFrame())) {
+ S = LCtx->getCurrentStackFrame()->getCallSite();
+ }
+
if (isa<ObjCArrayLiteral>(S)) {
os << "NSArray literal is an object with a +0 retain count";
}
@@ -1883,6 +1945,9 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
os << "oxed expression produces an object with a +0 retain count";
}
}
+ else if (isa<ObjCIvarRefExpr>(S)) {
+ os << "Object loaded from instance variable";
+ }
else {
if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
@@ -2034,7 +2099,6 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
switch (CurrV.getKind()) {
case RefVal::Owned:
case RefVal::NotOwned:
-
if (PrevV.getCount() == CurrV.getCount()) {
// Did an autorelease message get sent?
if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
@@ -2062,6 +2126,11 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
break;
case RefVal::Released:
+ if (CurrV.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
+ CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
+ os << "Strong instance variable relinquished. ";
+ }
os << "Object released.";
break;
@@ -2113,9 +2182,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
// Add the range by scanning the children of the statement for any bindings
// to Sym.
- for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
- I!=E; ++I)
- if (const Expr *Exp = dyn_cast_or_null<Expr>(*I))
+ for (const Stmt *Child : S->children())
+ if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
P->addRange(Exp->getSourceRange());
break;
@@ -2143,7 +2211,7 @@ static AllocationInfo
GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
SymbolRef Sym) {
const ExplodedNode *AllocationNode = N;
- const ExplodedNode *AllocationNodeInCurrentContext = N;
+ const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
const MemRegion *FirstBinding = nullptr;
const LocationContext *LeakContext = N->getLocationContext();
@@ -2173,10 +2241,15 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
// AllocationNode is the last node in which the symbol was tracked.
AllocationNode = N;
- // AllocationNodeInCurrentContext, is the last node in the current context
- // in which the symbol was tracked.
- if (NContext == LeakContext)
- AllocationNodeInCurrentContext = N;
+ // AllocationNodeInCurrentContext, is the last node in the current or
+ // parent context in which the symbol was tracked.
+ //
+ // Note that the allocation site might be in the parent conext. For example,
+ // the case where an allocation happens in a block that captures a reference
+ // to it and that reference is overwritten/dropped by another call to
+ // the block.
+ if (NContext == LeakContext || NContext->isParentOf(LeakContext))
+ AllocationNodeInCurrentOrParentContext = N;
// Find the last init that was called on the given symbol and store the
// init method's location context.
@@ -2214,7 +2287,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
FirstBinding = nullptr;
}
- return AllocationInfo(AllocationNodeInCurrentContext,
+ return AllocationInfo(AllocationNodeInCurrentOrParentContext,
FirstBinding,
InterestingMethodContext);
}
@@ -2345,20 +2418,8 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
ProgramPoint P = AllocNode->getLocation();
if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
AllocStmt = Exit->getCalleeContext()->getCallSite();
- else {
- // We are going to get a BlockEdge when the leak and allocation happen in
- // different, non-nested frames (contexts). For example, the case where an
- // allocation happens in a block that captures a reference to it and
- // that reference is overwritten/dropped by another call to the block.
- if (Optional<BlockEdge> Edge = P.getAs<BlockEdge>()) {
- if (Optional<CFGStmt> St = Edge->getDst()->front().getAs<CFGStmt>()) {
- AllocStmt = St->getStmt();
- }
- }
- else {
- AllocStmt = P.castAs<PostStmt>().getStmt();
- }
- }
+ else
+ AllocStmt = P.castAs<PostStmt>().getStmt();
assert(AllocStmt && "Cannot find allocation statement");
PathDiagnosticLocation AllocLocation =
@@ -2436,9 +2497,7 @@ public:
: ShouldResetSummaryLog(false),
IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
- virtual ~RetainCountChecker() {
- DeleteContainerSeconds(DeadSymbolTags);
- }
+ ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); }
void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng) const {
@@ -2709,7 +2768,6 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
if (hasErr) {
// FIXME: If we get an error during a bridge cast, should we report it?
- // Should we assert that there is no error?
return;
}
@@ -2720,16 +2778,14 @@ void RetainCountChecker::processObjCLiterals(CheckerContext &C,
const Expr *Ex) const {
ProgramStateRef state = C.getState();
const ExplodedNode *pred = C.getPredecessor();
- for (Stmt::const_child_iterator it = Ex->child_begin(), et = Ex->child_end() ;
- it != et ; ++it) {
- const Stmt *child = *it;
- SVal V = state->getSVal(child, pred->getLocationContext());
+ for (const Stmt *Child : Ex->children()) {
+ SVal V = state->getSVal(Child, pred->getLocationContext());
if (SymbolRef sym = V.getAsSymbol())
if (const RefVal* T = getRefBinding(state, sym)) {
RefVal::Kind hasErr = (RefVal::Kind) 0;
state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
if (hasErr) {
- processNonLeakError(state, child->getSourceRange(), hasErr, sym, C);
+ processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
return;
}
}
@@ -2774,17 +2830,64 @@ void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
C.addTransition(State);
}
+static bool wasLoadedFromIvar(SymbolRef Sym) {
+ if (auto DerivedVal = dyn_cast<SymbolDerived>(Sym))
+ return isa<ObjCIvarRegion>(DerivedVal->getRegion());
+ if (auto RegionVal = dyn_cast<SymbolRegionValue>(Sym))
+ return isa<ObjCIvarRegion>(RegionVal->getRegion());
+ return false;
+}
+
void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
CheckerContext &C) const {
+ Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
+ if (!IVarLoc)
+ return;
+
ProgramStateRef State = C.getState();
- // If an instance variable was previously accessed through a property,
- // it may have a synthesized refcount of +0. Override right now that we're
- // doing direct access.
- if (Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>())
- if (SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol())
- if (const RefVal *RV = getRefBinding(State, Sym))
- if (RV->isOverridable())
- State = removeRefBinding(State, Sym);
+ SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
+ if (!Sym || !wasLoadedFromIvar(Sym))
+ return;
+
+ // Accessing an ivar directly is unusual. If we've done that, be more
+ // forgiving about what the surrounding code is allowed to do.
+
+ QualType Ty = Sym->getType();
+ RetEffect::ObjKind Kind;
+ if (Ty->isObjCRetainableType())
+ Kind = RetEffect::ObjC;
+ else if (coreFoundation::isCFObjectRef(Ty))
+ Kind = RetEffect::CF;
+ else
+ return;
+
+ // If the value is already known to be nil, don't bother tracking it.
+ ConstraintManager &CMgr = State->getConstraintManager();
+ if (CMgr.isNull(State, Sym).isConstrainedTrue())
+ return;
+
+ if (const RefVal *RV = getRefBinding(State, Sym)) {
+ // If we've seen this symbol before, or we're only seeing it now because
+ // of something the analyzer has synthesized, don't do anything.
+ if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
+ isSynthesizedAccessor(C.getStackFrame())) {
+ return;
+ }
+
+ // Note that this value has been loaded from an ivar.
+ C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
+ return;
+ }
+
+ RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
+
+ // In a synthesized accessor, the effective retain count is +0.
+ if (isSynthesizedAccessor(C.getStackFrame())) {
+ C.addTransition(setRefBinding(State, Sym, PlusZero));
+ return;
+ }
+
+ State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
C.addTransition(State);
}
@@ -2828,16 +2931,6 @@ static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
return RetTy;
}
-static bool wasSynthesizedProperty(const ObjCMethodCall *Call,
- ExplodedNode *N) {
- if (!Call || !Call->getDecl()->isPropertyAccessor())
- return false;
-
- CallExitEnd PP = N->getLocation().castAs<CallExitEnd>();
- const StackFrameContext *Frame = PP.getCalleeContext();
- return Frame->getAnalysisDeclContext()->isBodyAutosynthesized();
-}
-
// We don't always get the exact modeling of the function with regards to the
// retain count checker even when the function is inlined. For example, we need
// to stop tracking the symbols which were marked with StopTrackingHard.
@@ -2872,24 +2965,45 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
if (Sym)
state = removeRefBinding(state, Sym);
- } else if (RE.getKind() == RetEffect::NotOwnedSymbol) {
- if (wasSynthesizedProperty(MsgInvocation, C.getPredecessor())) {
- // Believe the summary if we synthesized the body of a property getter
- // and the return value is currently untracked. If the corresponding
- // instance variable is later accessed directly, however, we're going to
- // want to override this state, so that the owning object can perform
- // reference counting operations on its own ivars.
- SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
- if (Sym && !getRefBinding(state, Sym))
- state = setRefBinding(state, Sym,
- RefVal::makeOverridableNotOwned(RE.getObjKind(),
- Sym->getType()));
- }
}
C.addTransition(state);
}
+static ProgramStateRef updateOutParameter(ProgramStateRef State,
+ SVal ArgVal,
+ ArgEffect Effect) {
+ auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
+ if (!ArgRegion)
+ return State;
+
+ QualType PointeeTy = ArgRegion->getValueType();
+ if (!coreFoundation::isCFObjectRef(PointeeTy))
+ return State;
+
+ SVal PointeeVal = State->getSVal(ArgRegion);
+ SymbolRef Pointee = PointeeVal.getAsLocSymbol();
+ if (!Pointee)
+ return State;
+
+ switch (Effect) {
+ case UnretainedOutParameter:
+ State = setRefBinding(State, Pointee,
+ RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
+ break;
+ case RetainedOutParameter:
+ // Do nothing. Retained out parameters will either point to a +1 reference
+ // or NULL, but the way you check for failure differs depending on the API.
+ // Consequently, we don't have a good way to track them yet.
+ break;
+
+ default:
+ llvm_unreachable("only for out parameters");
+ }
+
+ return State;
+}
+
void RetainCountChecker::checkSummary(const RetainSummary &Summ,
const CallEvent &CallOrMsg,
CheckerContext &C) const {
@@ -2903,9 +3017,12 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
SVal V = CallOrMsg.getArgSVal(idx);
- if (SymbolRef Sym = V.getAsLocSymbol()) {
+ ArgEffect Effect = Summ.getArg(idx);
+ if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
+ state = updateOutParameter(state, V, Effect);
+ } else if (SymbolRef Sym = V.getAsLocSymbol()) {
if (const RefVal *T = getRefBinding(state, Sym)) {
- state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr, C);
+ state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
if (hasErr) {
ErrorRange = CallOrMsg.getArgSourceRange(idx);
ErrorSym = Sym;
@@ -3054,6 +3171,11 @@ RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
case DecRefMsgAndStopTrackingHard:
llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
+ case UnretainedOutParameter:
+ case RetainedOutParameter:
+ llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
+ "not have ref state.");
+
case Dealloc:
// Any use of -dealloc in GC is *bad*.
if (C.isObjCGCEnabled()) {
@@ -3125,11 +3247,16 @@ RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
case RefVal::Owned:
assert(V.getCount() > 0);
- if (V.getCount() == 1)
- V = V ^ (E == DecRefBridgedTransferred ? RefVal::NotOwned
- : RefVal::Released);
- else if (E == DecRefAndStopTrackingHard)
+ if (V.getCount() == 1) {
+ if (E == DecRefBridgedTransferred ||
+ V.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly)
+ V = V ^ RefVal::NotOwned;
+ else
+ V = V ^ RefVal::Released;
+ } else if (E == DecRefAndStopTrackingHard) {
return removeRefBinding(state, sym);
+ }
V = V - 1;
break;
@@ -3139,6 +3266,13 @@ RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
if (E == DecRefAndStopTrackingHard)
return removeRefBinding(state, sym);
V = V - 1;
+ } else if (V.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly) {
+ // Assume that the instance variable was holding on the object at
+ // +1, and we just didn't know.
+ if (E == DecRefAndStopTrackingHard)
+ return removeRefBinding(state, sym);
+ V = V.releaseViaIvar() ^ RefVal::Released;
} else {
V = V ^ RefVal::ErrorReleaseNotOwned;
hasErr = V.getKind();
@@ -3162,6 +3296,16 @@ void RetainCountChecker::processNonLeakError(ProgramStateRef St,
RefVal::Kind ErrorKind,
SymbolRef Sym,
CheckerContext &C) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (const RefVal *RV = getRefBinding(St, Sym))
+ if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return;
+
ExplodedNode *N = C.generateSink(St);
if (!N)
return;
@@ -3173,31 +3317,31 @@ void RetainCountChecker::processNonLeakError(ProgramStateRef St,
case RefVal::ErrorUseAfterRelease:
if (!useAfterRelease)
useAfterRelease.reset(new UseAfterRelease(this));
- BT = &*useAfterRelease;
+ BT = useAfterRelease.get();
break;
case RefVal::ErrorReleaseNotOwned:
if (!releaseNotOwned)
releaseNotOwned.reset(new BadRelease(this));
- BT = &*releaseNotOwned;
+ BT = releaseNotOwned.get();
break;
case RefVal::ErrorDeallocGC:
if (!deallocGC)
deallocGC.reset(new DeallocGC(this));
- BT = &*deallocGC;
+ BT = deallocGC.get();
break;
case RefVal::ErrorDeallocNotOwned:
if (!deallocNotOwned)
deallocNotOwned.reset(new DeallocNotOwned(this));
- BT = &*deallocNotOwned;
+ BT = deallocNotOwned.get();
break;
}
assert(BT);
- CFRefReport *report = new CFRefReport(*BT, C.getASTContext().getLangOpts(),
- C.isObjCGCEnabled(), SummaryLog,
- N, Sym);
+ auto report = std::unique_ptr<BugReport>(
+ new CFRefReport(*BT, C.getASTContext().getLangOpts(), C.isObjCGCEnabled(),
+ SummaryLog, N, Sym));
report->addRange(ErrorRange);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
//===----------------------------------------------------------------------===//
@@ -3229,7 +3373,7 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// See if it's one of the specific functions we know how to eval.
bool canEval = false;
- QualType ResultTy = CE->getCallReturnType();
+ QualType ResultTy = CE->getCallReturnType(C.getASTContext());
if (ResultTy->isObjCIdType()) {
// Handle: id NSMakeCollectable(CFTypeRef)
canEval = II->isStr("NSMakeCollectable");
@@ -3388,6 +3532,15 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
RetEffect RE, RefVal X,
SymbolRef Sym,
ProgramStateRef state) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return;
+
// Any leaks or other errors?
if (X.isReturnedOwned() && X.getCount() == 0) {
if (RE.getKind() != RetEffect::NoRet) {
@@ -3417,33 +3570,37 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
if (N) {
const LangOptions &LOpts = C.getASTContext().getLangOpts();
bool GCEnabled = C.isObjCGCEnabled();
- CFRefReport *report =
- new CFRefLeakReport(*getLeakAtReturnBug(LOpts, GCEnabled),
- LOpts, GCEnabled, SummaryLog,
- N, Sym, C, IncludeAllocationLine);
-
- C.emitReport(report);
+ C.emitReport(std::unique_ptr<BugReport>(new CFRefLeakReport(
+ *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
+ SummaryLog, N, Sym, C, IncludeAllocationLine)));
}
}
}
} else if (X.isReturnedNotOwned()) {
if (RE.isOwned()) {
- // Trying to return a not owned object to a caller expecting an
- // owned object.
- state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
-
- static CheckerProgramPointTag ReturnNotOwnedTag(this,
- "ReturnNotOwnedForOwned");
- ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
- if (N) {
- if (!returnNotOwnedForOwned)
- returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
-
- CFRefReport *report =
- new CFRefReport(*returnNotOwnedForOwned,
- C.getASTContext().getLangOpts(),
- C.isObjCGCEnabled(), SummaryLog, N, Sym);
- C.emitReport(report);
+ if (X.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly) {
+ // Assume the method was trying to transfer a +1 reference from a
+ // strong ivar to the caller.
+ state = setRefBinding(state, Sym,
+ X.releaseViaIvar() ^ RefVal::ReturnedOwned);
+ } else {
+ // Trying to return a not owned object to a caller expecting an
+ // owned object.
+ state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
+
+ static CheckerProgramPointTag
+ ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
+
+ ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
+ if (N) {
+ if (!returnNotOwnedForOwned)
+ returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
+
+ C.emitReport(std::unique_ptr<BugReport>(new CFRefReport(
+ *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
+ C.isObjCGCEnabled(), SummaryLog, N, Sym)));
+ }
}
}
}
@@ -3594,6 +3751,14 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
if (V.getKind() == RefVal::ReturnedOwned)
++Cnt;
+ // If we would over-release here, but we know the value came from an ivar,
+ // assume it was a strong ivar that's just been relinquished.
+ if (ACnt > Cnt &&
+ V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
+ V = V.releaseViaIvar();
+ --ACnt;
+ }
+
if (ACnt <= Cnt) {
if (ACnt == Cnt) {
V.clearCounts();
@@ -3608,6 +3773,15 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
return setRefBinding(state, Sym, V);
}
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return state;
+
// Woah! More autorelease counts then retain counts left.
// Emit hard error.
V = V ^ RefVal::ErrorOverAutorelease;
@@ -3628,10 +3802,9 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
overAutorelease.reset(new OverAutorelease(this));
const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
- CFRefReport *report =
- new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
- SummaryLog, N, Sym, os.str());
- Ctx.emitReport(report);
+ Ctx.emitReport(std::unique_ptr<BugReport>(
+ new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
+ SummaryLog, N, Sym, os.str())));
}
return nullptr;
@@ -3641,11 +3814,22 @@ ProgramStateRef
RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
SymbolRef sid, RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) const {
- bool hasLeak = false;
- if (V.isOwned())
+ bool hasLeak;
+
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ hasLeak = false;
+ else if (V.isOwned())
hasLeak = true;
else if (V.isNotOwned() || V.isReturnedOwned())
hasLeak = (V.getCount() > 0);
+ else
+ hasLeak = false;
if (!hasLeak)
return removeRefBinding(state, sid);
@@ -3672,10 +3856,9 @@ RetainCountChecker::processLeaks(ProgramStateRef state,
: getLeakAtReturnBug(LOpts, GCEnabled);
assert(BT && "BugType not initialized.");
- CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, GCEnabled,
- SummaryLog, N, *I, Ctx,
- IncludeAllocationLine);
- Ctx.emitReport(report);
+ Ctx.emitReport(std::unique_ptr<BugReport>(
+ new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
+ IncludeAllocationLine)));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index b1cde6b..acbd0d9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -80,11 +80,10 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
// reference is outside the range.
// Generate a report for this bug.
- BugReport *report =
- new BugReport(*BT, BT->getDescription(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
report->addRange(RetE->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 6622313..2668ac1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -84,12 +84,12 @@ static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
if (!N)
return;
- BugReport *Report = new BugReport(BT, BT.getDescription(), N);
+ auto Report = llvm::make_unique<BugReport>(BT, BT.getDescription(), N);
Report->addRange(RetE->getSourceRange());
bugreporter::trackNullOrUndefValue(N, TrackingE ? TrackingE : RetE, *Report);
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void ReturnUndefChecker::emitUndef(CheckerContext &C, const Expr *RetE) const {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index ccf816c..c22e78b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -214,11 +214,11 @@ void SimpleStreamChecker::reportDoubleClose(SymbolRef FileDescSym,
return;
// Generate the report.
- BugReport *R = new BugReport(*DoubleCloseBugType,
+ auto R = llvm::make_unique<BugReport>(*DoubleCloseBugType,
"Closing a previously closed file stream", ErrNode);
R->addRange(Call.getSourceRange());
R->markInteresting(FileDescSym);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void SimpleStreamChecker::reportLeaks(ArrayRef<SymbolRef> LeakedStreams,
@@ -227,10 +227,10 @@ void SimpleStreamChecker::reportLeaks(ArrayRef<SymbolRef> LeakedStreams,
// Attach bug reports to the leak node.
// TODO: Identify the leaked file descriptor.
for (SymbolRef LeakedStream : LeakedStreams) {
- BugReport *R = new BugReport(*LeakBugType,
+ auto R = llvm::make_unique<BugReport>(*LeakBugType,
"Opened file is never closed; potential resource leak", ErrNode);
R->markInteresting(LeakedStream);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 327a9e0..813c811 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -108,12 +108,12 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *
llvm::raw_svector_ostream os(buf);
SourceRange range = genName(os, R, C.getASTContext());
os << " returned to caller";
- BugReport *report = new BugReport(*BT_returnstack, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_returnstack, os.str(), N);
report->addRange(RetE->getSourceRange());
if (range.isValid())
report->addRange(range);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
@@ -231,11 +231,11 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
os << *VR->getDecl()
<< "' upon returning to the caller. This will be a dangling reference";
- BugReport *report = new BugReport(*BT_stackleak, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_stackleak, os.str(), N);
if (range.isValid())
report->addRange(range);
- Ctx.emitReport(report);
+ Ctx.emitReport(std::move(report));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 894765a..2109a75 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -277,9 +277,8 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
new BuiltinBug(this, "Illegal whence argument",
"The whence argument to fseek() should be "
"SEEK_SET, SEEK_END, or SEEK_CUR."));
- BugReport *R = new BugReport(*BT_illegalwhence,
- BT_illegalwhence->getDescription(), N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_illegalwhence, BT_illegalwhence->getDescription(), N));
}
}
@@ -354,8 +353,8 @@ ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
if (!BT_nullfp)
BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer",
"Stream pointer might be NULL."));
- BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_nullfp, BT_nullfp->getDescription(), N));
}
return nullptr;
}
@@ -385,9 +384,8 @@ ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
BT_doubleclose.reset(new BuiltinBug(
this, "Double fclose", "Try to close a file Descriptor already"
" closed. Cause undefined behaviour."));
- BugReport *R = new BugReport(*BT_doubleclose,
- BT_doubleclose->getDescription(), N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_doubleclose, BT_doubleclose->getDescription(), N));
}
return nullptr;
}
@@ -414,9 +412,8 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
BT_ResourceLeak.reset(new BuiltinBug(
this, "Resource Leak",
"Opened File never closed. Potential Resource leak."));
- BugReport *R = new BugReport(*BT_ResourceLeak,
- BT_ResourceLeak->getDescription(), N);
- C.emitReport(R);
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
index d33c977..6e24775 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
@@ -50,9 +50,9 @@ void TaintTesterChecker::checkPostStmt(const Expr *E,
if (State->isTainted(E, C.getLocationContext())) {
if (ExplodedNode *N = C.addTransition()) {
initBugType();
- BugReport *report = new BugReport(*BT, "tainted",N);
+ auto report = llvm::make_unique<BugReport>(*BT, "tainted",N);
report->addRange(E->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index 083075d..638701d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -171,14 +171,14 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
if (!DivZeroBug)
DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));
- BugReport *R =
- new BugReport(*DivZeroBug, "Value being compared against zero has "
- "already been used for division",
- N);
+ auto R = llvm::make_unique<BugReport>(
+ *DivZeroBug, "Value being compared against zero has already been used "
+ "for division",
+ N);
R->addVisitor(llvm::make_unique<DivisionBRVisitor>(Val.getAsSymbol(),
C.getStackFrame()));
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index fc49a46..1d8ef99 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -37,12 +37,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
if (!MatchesCriteria(Ex))
return nullptr;
- for (Stmt::const_child_iterator I = Ex->child_begin(),
- E = Ex->child_end();I!=E;++I)
- if (const Expr *ExI = dyn_cast_or_null<Expr>(*I)) {
- const Expr *E2 = FindExpr(ExI);
- if (E2) return E2;
- }
+ for (const Stmt *SubStmt : Ex->children())
+ if (const Expr *ExI = dyn_cast_or_null<Expr>(SubStmt))
+ if (const Expr *E2 = FindExpr(ExI))
+ return E2;
return Ex;
}
@@ -98,11 +96,11 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
Ex = FindIt.FindExpr(Ex);
// Emit the bug report.
- BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
bugreporter::trackNullOrUndefValue(N, Ex, *R);
R->addRange(Ex->getSourceRange());
- Ctx.emitReport(R);
+ Ctx.emitReport(std::move(R));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 8976e0a..53fd069 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -40,13 +40,10 @@ static const DeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
if (BR->getDecl() == VD)
return BR;
- for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
- I!=E; ++I)
- if (const Stmt *child = *I) {
- const DeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
- if (BR)
+ for (const Stmt *Child : S->children())
+ if (Child)
+ if (const DeclRefExpr *BR = FindBlockDeclRefExpr(Child, VD))
return BR;
- }
return nullptr;
}
@@ -89,14 +86,14 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
os << "Variable '" << VD->getName()
<< "' is uninitialized when captured by block";
- BugReport *R = new BugReport(*BT, os.str(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, os.str(), N);
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
R->addRange(Ex->getSourceRange());
R->addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
*V, VR, /*EnableNullFPSuppression*/ false));
R->disablePathPruning();
// need location of block
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index f3f4dce..5353310 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -84,7 +84,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
<< BinaryOperator::getOpcodeStr(B->getOpcode())
<< "' expression is undefined";
}
- BugReport *report = new BugReport(*BT, OS.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (Ex) {
report->addRange(Ex->getSourceRange());
bugreporter::trackNullOrUndefValue(N, Ex, *report);
@@ -92,7 +92,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
else
bugreporter::trackNullOrUndefValue(N, B, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index e952671..ba4daf8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -53,10 +53,10 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
// Generate a report for this bug.
- BugReport *R = new BugReport(*BT, BT->getName(), N);
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
R->addRange(A->getIdx()->getSourceRange());
bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R);
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index bd4493d..81c96c4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -83,12 +83,12 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
break;
}
- BugReport *R = new BugReport(*BT, str, N);
+ auto R = llvm::make_unique<BugReport>(*BT, str, N);
if (ex) {
R->addRange(ex->getSourceRange());
bugreporter::trackNullOrUndefValue(N, ex, *R);
}
- C.emitReport(R);
+ C.emitReport(std::move(R));
}
void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 4bfed85..a799b4c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -83,9 +83,9 @@ void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
LazyInitialize(BT_open, "Improper use of 'open'");
- BugReport *Report = new BugReport(*BT_open, Msg, N);
+ auto Report = llvm::make_unique<BugReport>(*BT_open, Msg, N);
Report->addRange(SR);
- C.emitReport(Report);
+ C.emitReport(std::move(Report));
}
void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
@@ -200,9 +200,9 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
LazyInitialize(BT_pthreadOnce, "Improper use of 'pthread_once'");
- BugReport *report = new BugReport(*BT_pthreadOnce, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_pthreadOnce, os.str(), N);
report->addRange(CE->getArg(0)->getSourceRange());
- C.emitReport(report);
+ C.emitReport(std::move(report));
}
//===----------------------------------------------------------------------===//
@@ -241,11 +241,11 @@ bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
SmallString<256> S;
llvm::raw_svector_ostream os(S);
os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
- BugReport *report = new BugReport(*BT_mallocZero, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
report->addRange(arg->getSourceRange());
bugreporter::trackNullOrUndefValue(N, arg, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index cceffef..80384bb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -72,10 +72,10 @@ void VLASizeChecker::reportBug(VLASize_Kind Kind,
break;
}
- BugReport *report = new BugReport(*BT, os.str(), N);
+ auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(SizeE->getSourceRange());
bugreporter::trackNullOrUndefValue(N, SizeE, *report);
- C.emitReport(report);
+ C.emitReport(std::move(report));
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index 7e1fc1e..f6ef4ae 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -125,9 +125,9 @@ public:
//===----------------------------------------------------------------------===//
void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
- if (Stmt *child = *I)
- Visit(child);
+ for (Stmt *Child : S->children())
+ if (Child)
+ Visit(Child);
}
void WalkAST::VisitCallExpr(CallExpr *CE) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index d717e3f..1696bcf 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -13,12 +13,14 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+using namespace ento;
using namespace llvm;
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
@@ -100,12 +102,37 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) {
static StringRef toString(bool b) { return b ? "true" : "false"; }
-bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) {
+StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
+ StringRef OptionName,
+ StringRef Default,
+ bool SearchInParents) {
+ // Search for a package option if the option for the checker is not specified
+ // and search in parents is enabled.
+ ConfigTable::const_iterator E = Config.end();
+ do {
+ ConfigTable::const_iterator I =
+ Config.find((Twine(CheckerName) + ":" + OptionName).str());
+ if (I != E)
+ return StringRef(I->getValue());
+ size_t Pos = CheckerName.rfind('.');
+ if (Pos == StringRef::npos)
+ return Default;
+ CheckerName = CheckerName.substr(0, Pos);
+ } while (!CheckerName.empty() && SearchInParents);
+ return Default;
+}
+
+bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
// FIXME: We should emit a warning here if the value is something other than
// "true", "false", or the empty string (meaning the default value),
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
+ StringRef Default = toString(DefaultVal);
StringRef V =
- Config.insert(std::make_pair(Name, toString(DefaultVal))).first->second;
+ C ? getCheckerOption(C->getTagDescription(), Name, Default,
+ SearchInParents)
+ : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
return llvm::StringSwitch<bool>(V)
.Case("true", true)
.Case("false", false)
@@ -113,9 +140,10 @@ bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) {
}
bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
- bool DefaultVal) {
+ bool DefaultVal, const CheckerBase *C,
+ bool SearchInParents) {
if (!V.hasValue())
- V = getBooleanOption(Name, DefaultVal);
+ V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
return V.getValue();
}
@@ -199,19 +227,35 @@ bool AnalyzerOptions::shouldWriteStableReportFilename() {
/* Default = */ false);
}
-int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) {
+int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
SmallString<10> StrBuf;
llvm::raw_svector_ostream OS(StrBuf);
OS << DefaultVal;
- StringRef V = Config.insert(std::make_pair(Name, OS.str())).first->second;
+ StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
+ SearchInParents)
+ : StringRef(Config.insert(std::make_pair(Name, OS.str()))
+ .first->second);
+
int Res = DefaultVal;
bool b = V.getAsInteger(10, Res);
assert(!b && "analyzer-config option should be numeric");
- (void) b;
+ (void)b;
return Res;
}
+StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
+ StringRef DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
+ return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
+ SearchInParents)
+ : StringRef(
+ Config.insert(std::make_pair(Name, DefaultVal)).first->second);
+}
+
unsigned AnalyzerOptions::getAlwaysInlineSize() {
if (!AlwaysInlineSize.hasValue())
AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
@@ -281,4 +325,3 @@ bool AnalyzerOptions::shouldPrunePaths() {
bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
return getBooleanOption("cfg-conditional-static-initializers", true);
}
-
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index 0e90566..3c3f41a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -154,9 +154,13 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
return &getValue( V1 * V2 );
case BO_Div:
+ if (V2 == 0) // Avoid division by zero
+ return nullptr;
return &getValue( V1 / V2 );
case BO_Rem:
+ if (V2 == 0) // Avoid division by zero
+ return nullptr;
return &getValue( V1 % V2 );
case BO_Add:
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index dff81e3..e4db64f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1250,10 +1250,8 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
// Fall through.
case Stmt::BinaryOperatorClass:
case Stmt::UnaryOperatorClass: {
- for (Stmt::const_child_iterator CI = Ex->child_begin(),
- CE = Ex->child_end();
- CI != CE; ++CI) {
- if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) {
+ for (const Stmt *SubStmt : Ex->children()) {
+ if (const Expr *child = dyn_cast_or_null<Expr>(SubStmt)) {
IE.insert(child);
SVal ChildV = State->getSVal(child, LCtx);
R.markInteresting(ChildV);
@@ -2702,22 +2700,22 @@ const Stmt *BugReport::getStmt() const {
return S;
}
-std::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
-BugReport::getRanges() {
- // If no custom ranges, add the range of the statement corresponding to
- // the error node.
- if (Ranges.empty()) {
- if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
- addRange(E->getSourceRange());
- else
- return std::make_pair(ranges_iterator(), ranges_iterator());
- }
+llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() {
+ // If no custom ranges, add the range of the statement corresponding to
+ // the error node.
+ if (Ranges.empty()) {
+ if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
+ addRange(E->getSourceRange());
+ else
+ return llvm::make_range(ranges_iterator(), ranges_iterator());
+ }
- // User-specified absence of range info.
- if (Ranges.size() == 1 && !Ranges.begin()->isValid())
- return std::make_pair(ranges_iterator(), ranges_iterator());
+ // User-specified absence of range info.
+ if (Ranges.size() == 1 && !Ranges.begin()->isValid())
+ return llvm::make_range(ranges_iterator(), ranges_iterator());
- return std::make_pair(Ranges.begin(), Ranges.end());
+ return llvm::iterator_range<BugReport::ranges_iterator>(Ranges.begin(),
+ Ranges.end());
}
PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
@@ -2763,9 +2761,7 @@ void BugReporter::FlushReports() {
// warnings and new BugTypes.
// FIXME: Only NSErrorChecker needs BugType's FlushReports.
// Turn NSErrorChecker into a proper checker and remove this.
- SmallVector<const BugType*, 16> bugTypes;
- for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
- bugTypes.push_back(*I);
+ SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
for (SmallVectorImpl<const BugType *>::iterator
I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
const_cast<BugType*>(*I)->FlushReports(*this);
@@ -3055,8 +3051,7 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
// Now take the pieces and construct a new PathDiagnostic.
path.clear();
- for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I)
- path.push_back(*I);
+ path.insert(path.end(), Pieces.begin(), Pieces.end());
}
bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
@@ -3227,10 +3222,7 @@ void BugReporter::Register(BugType *BT) {
BugTypes = F.add(BugTypes, BT);
}
-void BugReporter::emitReport(BugReport* R) {
- // To guarantee memory release.
- std::unique_ptr<BugReport> UniqueR(R);
-
+void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
if (const ExplodedNode *E = R->getErrorNode()) {
const AnalysisDeclContext *DeclCtx =
E->getLocationContext()->getAnalysisDeclContext();
@@ -3261,11 +3253,11 @@ void BugReporter::emitReport(BugReport* R) {
BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
if (!EQ) {
- EQ = new BugReportEquivClass(std::move(UniqueR));
+ EQ = new BugReportEquivClass(std::move(R));
EQClasses.InsertNode(EQ, InsertPos);
EQClassesVector.push_back(EQ);
} else
- EQ->AddReport(std::move(UniqueR));
+ EQ->AddReport(std::move(R));
}
@@ -3434,10 +3426,8 @@ void BugReporter::FlushReport(BugReport *exampleReport,
PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
L, exampleReport->getDescription());
- BugReport::ranges_iterator Beg, End;
- std::tie(Beg, End) = exampleReport->getRanges();
- for ( ; Beg != End; ++Beg)
- piece->addRange(*Beg);
+ for (const SourceRange &Range : exampleReport->getRanges())
+ piece->addRange(Range);
D->setEndOfPath(std::move(piece));
}
@@ -3467,12 +3457,12 @@ void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
// 'BT' is owned by BugReporter.
BugType *BT = getBugTypeForName(CheckName, name, category);
- BugReport *R = new BugReport(*BT, str, Loc);
+ auto R = llvm::make_unique<BugReport>(*BT, str, Loc);
R->setDeclWithIssue(DeclWithIssue);
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
I != E; ++I)
R->addRange(*I);
- emitReport(R);
+ emitReport(std::move(R));
}
BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 2d56bd0..f2915ed 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -111,15 +111,14 @@ std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
PathDiagnosticLocation L =
PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
- BugReport::ranges_iterator Beg, End;
- std::tie(Beg, End) = BR.getRanges();
+ const auto &Ranges = BR.getRanges();
// Only add the statement itself as a range if we didn't specify any
// special ranges for this report.
- auto P = llvm::make_unique<PathDiagnosticEventPiece>(L, BR.getDescription(),
- Beg == End);
- for (; Beg != End; ++Beg)
- P->addRange(*Beg);
+ auto P = llvm::make_unique<PathDiagnosticEventPiece>(
+ L, BR.getDescription(), Ranges.begin() == Ranges.end());
+ for (const SourceRange &Range : Ranges)
+ P->addRange(Range);
return std::move(P);
}
@@ -1131,9 +1130,8 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
}
}
- for (Stmt::const_child_iterator I = Head->child_begin();
- I != Head->child_end(); ++I)
- WorkList.push_back(*I);
+ for (const Stmt *SubStmt : Head->children())
+ WorkList.push_back(SubStmt);
}
}
@@ -1530,7 +1528,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
return nullptr;
} else {
- // If the the complete 'std' suppression is not enabled, suppress reports
+ // If the complete 'std' suppression is not enabled, suppress reports
// from the 'std' namespace that are known to produce false positives.
// The analyzer issues a false use-after-free when std::list::pop_front
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index f673544..8542f7d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -785,7 +785,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
if (E->isInstanceMessage()) {
- // Find the the receiver type.
+ // Find the receiver type.
const ObjCObjectPointerType *ReceiverT = nullptr;
bool CanBeSubClassed = false;
QualType SupersType = E->getSuperType();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
index 1a3965a..2235211 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
@@ -36,11 +36,3 @@ raw_ostream& clang::ento::operator<<(raw_ostream &Out,
Out << Checker.getCheckName().getName();
return Out;
}
-
-void Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck
- >::anchor() { }
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index 28df695..3d9a815 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -22,11 +22,9 @@ bool clang::ento::containsMacro(const Stmt *S) {
if (S->getLocEnd().isMacroID())
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsMacro(child))
- return true;
+ for (const Stmt *Child : S->children())
+ if (Child && containsMacro(Child))
+ return true;
return false;
}
@@ -38,11 +36,9 @@ bool clang::ento::containsEnum(const Stmt *S) {
if (DR && isa<EnumConstantDecl>(DR->getDecl()))
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsEnum(child))
- return true;
+ for (const Stmt *Child : S->children())
+ if (Child && containsEnum(Child))
+ return true;
return false;
}
@@ -56,11 +52,9 @@ bool clang::ento::containsStaticLocal(const Stmt *S) {
if (VD->isStaticLocal())
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsStaticLocal(child))
- return true;
+ for (const Stmt *Child : S->children())
+ if (Child && containsStaticLocal(Child))
+ return true;
return false;
}
@@ -70,11 +64,9 @@ bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
if (isa<OffsetOfExpr>(S))
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsBuiltinOffsetOf(child))
- return true;
+ for (const Stmt *Child : S->children())
+ if (Child && containsBuiltinOffsetOf(Child))
+ return true;
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index b64e30b..6ba64f5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -8,7 +8,10 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/raw_ostream.h"
@@ -111,6 +114,28 @@ void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
}
}
+void CheckerRegistry::validateCheckerOptions(const AnalyzerOptions &opts,
+ DiagnosticsEngine &diags) const {
+ for (auto &config : opts.Config) {
+ size_t pos = config.getKey().find(':');
+ if (pos == StringRef::npos)
+ continue;
+
+ bool hasChecker = false;
+ StringRef checkerName = config.getKey().substr(0, pos);
+ for (auto &checker : Checkers) {
+ if (checker.FullName.startswith(checkerName) &&
+ (checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
+ hasChecker = true;
+ break;
+ }
+ }
+ if (!hasChecker) {
+ diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
+ }
+ }
+}
+
void CheckerRegistry::printHelp(raw_ostream &out,
size_t maxNameChars) const {
// FIXME: Alphabetical sort puts 'experimental' in the middle.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 4699df8..a3239f5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -816,11 +816,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPTaskyieldDirectiveClass:
case Stmt::OMPBarrierDirectiveClass:
case Stmt::OMPTaskwaitDirectiveClass:
+ case Stmt::OMPTaskgroupDirectiveClass:
case Stmt::OMPFlushDirectiveClass:
case Stmt::OMPOrderedDirectiveClass:
case Stmt::OMPAtomicDirectiveClass:
case Stmt::OMPTargetDirectiveClass:
case Stmt::OMPTeamsDirectiveClass:
+ case Stmt::OMPCancellationPointDirectiveClass:
+ case Stmt::OMPCancelDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
@@ -859,6 +862,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// Cases not handled yet; but will handle some day.
case Stmt::DesignatedInitExprClass:
+ case Stmt::DesignatedInitUpdateExprClass:
case Stmt::ExtVectorElementExprClass:
case Stmt::ImaginaryLiteralClass:
case Stmt::ObjCAtCatchStmtClass:
@@ -891,6 +895,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXBoolLiteralExprClass:
case Stmt::ObjCBoolLiteralExprClass:
case Stmt::FloatingLiteralClass:
+ case Stmt::NoInitExprClass:
case Stmt::SizeOfPackExprClass:
case Stmt::StringLiteralClass:
case Stmt::ObjCStringLiteralClass:
@@ -1901,6 +1906,9 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currBldrCtx);
+ assert(A->isGLValue() ||
+ (!AMgr.getLangOpts().CPlusPlus &&
+ A->getType().isCForbiddenLValueType()));
for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
ei = checkerPreStmt.end(); it != ei; ++it) {
@@ -1909,7 +1917,6 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
SVal V = state->getLValue(A->getType(),
state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
- assert(A->isGLValue());
Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
}
@@ -2646,17 +2653,6 @@ struct DOTGraphTraits<ExplodedNode*> :
} // end llvm namespace
#endif
-#ifndef NDEBUG
-template <typename ITERATOR>
-ExplodedNode *GetGraphNode(ITERATOR I) { return *I; }
-
-template <> ExplodedNode*
-GetGraphNode<llvm::DenseMap<ExplodedNode*, Expr*>::iterator>
- (llvm::DenseMap<ExplodedNode*, Expr*>::iterator I) {
- return I->first;
-}
-#endif
-
void ExprEngine::ViewGraph(bool trim) {
#ifndef NDEBUG
if (trim) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index ffda527..1777ea9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -31,7 +31,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
ExplodedNodeSet Tmp2;
getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this);
- // With both the LHS and RHS evaluated, process the operation itself.
+ // With both the LHS and RHS evaluated, process the operation itself.
for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end();
it != ei; ++it) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 88b5464..cfcf7c6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -22,6 +22,7 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -45,7 +46,7 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {
public:
HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
- virtual ~HTMLDiagnostics() { FlushDiagnostics(nullptr); }
+ ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override;
@@ -282,7 +283,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
if (std::error_code EC =
- llvm::sys::fs::createUniqueFile(Model.str(), FD, ResultPath)) {
+ llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
llvm::errs() << "warning: could not create file in '" << Directory
<< "': " << EC.message() << '\n';
return;
@@ -302,12 +303,12 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
<< "-" << i << ".html";
llvm::sys::path::append(Model, Directory,
filename.str());
- EC = llvm::sys::fs::openFileForWrite(Model.str(),
+ EC = llvm::sys::fs::openFileForWrite(Model,
FD,
llvm::sys::fs::F_RW |
llvm::sys::fs::F_Excl);
- if (EC && EC != std::errc::file_exists) {
- llvm::errs() << "warning: could not create file '" << Model.str()
+ if (EC && EC != llvm::errc::file_exists) {
+ llvm::errs() << "warning: could not create file '" << Model
<< "': " << EC.message() << '\n';
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 76cead6..5ac8458 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -824,9 +824,12 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
QualType T;
if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
T = TSI->getType();
- else
- T = getContext().getFunctionNoProtoType(getContext().VoidTy);
-
+ if (T.isNull())
+ T = getContext().VoidTy;
+ if (!T->getAs<FunctionType>())
+ T = getContext().getFunctionNoProtoType(T);
+ T = getContext().getBlockPointerType(T);
+
const BlockTextRegion *BTR =
getBlockTextRegion(BD, C.getCanonicalType(T),
STC->getAnalysisDeclContext());
@@ -1372,10 +1375,11 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
return;
AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
- AnalysisDeclContext::referenced_decls_iterator I, E;
- std::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
+ const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl());
+ auto NumBlockVars =
+ std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end());
- if (I == E) {
+ if (NumBlockVars == 0) {
ReferencedVars = (void*) 0x1;
return;
}
@@ -1386,14 +1390,14 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
typedef BumpVector<const MemRegion*> VarVec;
VarVec *BV = (VarVec*) A.Allocate<VarVec>();
- new (BV) VarVec(BC, E - I);
+ new (BV) VarVec(BC, NumBlockVars);
VarVec *BVOriginal = (VarVec*) A.Allocate<VarVec>();
- new (BVOriginal) VarVec(BC, E - I);
+ new (BVOriginal) VarVec(BC, NumBlockVars);
- for ( ; I != E; ++I) {
+ for (const VarDecl *VD : ReferencedBlockVars) {
const VarRegion *VR = nullptr;
const VarRegion *OriginalVR = nullptr;
- std::tie(VR, OriginalVR) = getCaptureRegions(*I);
+ std::tie(VR, OriginalVR) = getCaptureRegions(VD);
assert(VR);
assert(OriginalVR);
BV->push_back(VR, BC);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index b971fff..c490031 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -432,11 +432,15 @@ void PathDiagnosticConsumer::FlushDiagnostics(
// Sort the diagnostics so that they are always emitted in a deterministic
// order.
- if (!BatchDiags.empty())
- std::sort(BatchDiags.begin(), BatchDiags.end(),
- [](const PathDiagnostic *X, const PathDiagnostic *Y) {
- return X != Y && compare(*X, *Y);
- });
+ int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
+ [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
+ assert(*X != *Y && "PathDiagnostics not uniqued!");
+ if (compare(**X, **Y))
+ return -1;
+ assert(compare(**Y, **X) && "Not a total order!");
+ return 1;
+ };
+ array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
FlushDiagnosticsImpl(BatchDiags, Files);
@@ -452,7 +456,7 @@ void PathDiagnosticConsumer::FlushDiagnostics(
}
PathDiagnosticConsumer::FilesMade::~FilesMade() {
- for (PDFileEntry &Entry : *this)
+ for (PDFileEntry &Entry : Set)
Entry.~PDFileEntry();
}
@@ -462,11 +466,11 @@ void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
llvm::FoldingSetNodeID NodeID;
NodeID.Add(PD);
void *InsertPos;
- PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
+ PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
if (!Entry) {
Entry = Alloc.Allocate<PDFileEntry>();
Entry = new (Entry) PDFileEntry(NodeID);
- InsertNode(Entry, InsertPos);
+ Set.InsertNode(Entry, InsertPos);
}
// Allocate persistent storage for the file name.
@@ -483,7 +487,7 @@ PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
llvm::FoldingSetNodeID NodeID;
NodeID.Add(PD);
void *InsertPos;
- PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
+ PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
if (!Entry)
return nullptr;
return &Entry->files;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index a2c66f8..e0aff58 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -37,7 +37,7 @@ namespace {
const LangOptions &LangOpts,
bool supportsMultipleFiles);
- virtual ~PlistDiagnostics() {}
+ ~PlistDiagnostics() override {}
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override;
@@ -106,13 +106,14 @@ static void ReportControlFlow(raw_ostream &o,
// by forcing to use only the beginning of the range. This simplifies the layout
// logic for clients.
Indent(o, indent) << "<key>start</key>\n";
- SourceLocation StartEdge = I->getStart().asRange().getBegin();
- EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(StartEdge), FM,
+ SourceRange StartEdge(
+ SM.getExpansionLoc(I->getStart().asRange().getBegin()));
+ EmitRange(o, SM, Lexer::getAsCharRange(StartEdge, SM, LangOpts), FM,
indent + 1);
Indent(o, indent) << "<key>end</key>\n";
- SourceLocation EndEdge = I->getEnd().asRange().getBegin();
- EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(EndEdge), FM,
+ SourceRange EndEdge(SM.getExpansionLoc(I->getEnd().asRange().getBegin()));
+ EmitRange(o, SM, Lexer::getAsCharRange(EndEdge, SM, LangOpts), FM,
indent + 1);
--indent;
@@ -154,7 +155,7 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
FullSourceLoc L = P.getLocation().asLocation();
Indent(o, indent) << "<key>location</key>\n";
- EmitLocation(o, SM, LangOpts, L, FM, indent);
+ EmitLocation(o, SM, L, FM, indent);
// Output the ranges (if any).
ArrayRef<SourceRange> Ranges = P.getRanges();
@@ -163,11 +164,10 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
Indent(o, indent) << "<key>ranges</key>\n";
Indent(o, indent) << "<array>\n";
++indent;
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
- I != E; ++I) {
- EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(*I), FM,
- indent + 1);
- }
+ for (auto &R : Ranges)
+ EmitRange(o, SM,
+ Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts),
+ FM, indent + 1);
--indent;
Indent(o, indent) << "</array>\n";
}
@@ -387,7 +387,9 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
EmitString(o, D->getCategory()) << '\n';
o << " <key>type</key>";
EmitString(o, D->getBugType()) << '\n';
-
+ o << " <key>check_name</key>";
+ EmitString(o, D->getCheckName()) << '\n';
+
// Output information about the semantic context where
// the issue occurred.
if (const Decl *DeclWithIssue = D->getDeclWithIssue()) {
@@ -453,7 +455,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Output the location of the bug.
o << " <key>location</key>\n";
- EmitLocation(o, *SM, LangOpts, D->getLocation().asLocation(), FM, 2);
+ EmitLocation(o, *SM, D->getLocation().asLocation(), FM, 2);
// Output the diagnostic to the sub-diagnostic client, if any.
if (!filesMade->empty()) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 4505622..6d41fc2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -767,7 +767,7 @@ static inline bool isUnionField(const FieldRegion *FR) {
typedef SmallVector<const FieldDecl *, 8> FieldVector;
-void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
+static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
const MemRegion *Base = K.getConcreteOffsetRegion();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
index a72d1d4..135cd4e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -27,7 +27,7 @@ class SimpleConstraintManager : public ConstraintManager {
public:
SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB)
: SU(subengine), SVB(SB) {}
- virtual ~SimpleConstraintManager();
+ ~SimpleConstraintManager() override;
//===------------------------------------------------------------------===//
// Common implementation for the interface provided by ConstraintManager.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index df9e4d6..b3cab87c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -29,7 +29,7 @@ public:
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
ProgramStateManager &stateMgr)
: SValBuilder(alloc, context, stateMgr) {}
- virtual ~SimpleSValBuilder() {}
+ ~SimpleSValBuilder() override {}
SVal evalMinus(NonLoc val) override;
SVal evalComplement(NonLoc val) override;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 183ef35..c957a65 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -92,7 +92,7 @@ class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
public:
ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
: Diag(Diag), IncludePath(false) {}
- virtual ~ClangDiagPathDiagConsumer() {}
+ ~ClangDiagPathDiagConsumer() override {}
StringRef getName() const override { return "ClangDiags"; }
bool supportsLogicalOpControlFlow() const override { return true; }
@@ -199,7 +199,7 @@ public:
}
}
- ~AnalysisConsumer() {
+ ~AnalysisConsumer() override {
if (Opts->PrintStats)
delete TUTotalTimer;
}
@@ -373,8 +373,7 @@ public:
return true;
}
- virtual void
- AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
+ void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
PathConsumers.push_back(Consumer);
}
@@ -589,8 +588,11 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
// - Header files: run non-path-sensitive checks only.
// - System headers: don't run any checks.
SourceManager &SM = Ctx->getSourceManager();
- SourceLocation SL = SM.getExpansionLoc(D->getLocation());
- if (!Opts->AnalyzeAll && !SM.isInMainFile(SL)) {
+ SourceLocation SL = D->hasBody() ? D->getBody()->getLocStart()
+ : D->getLocation();
+ SL = SM.getExpansionLoc(SL);
+
+ if (!Opts->AnalyzeAll && !SM.isWrittenInMainFile(SL)) {
if (SL.isInvalid() || SM.isInSystemHeader(SL))
return AM_None;
return Mode & ~AM_Path;
@@ -724,7 +726,7 @@ class UbigraphViz : public ExplodedNode::Auditor {
public:
UbigraphViz(std::unique_ptr<raw_ostream> Out, StringRef Filename);
- ~UbigraphViz();
+ ~UbigraphViz() override;
void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) override;
};
@@ -735,7 +737,7 @@ static std::unique_ptr<ExplodedNode::Auditor> CreateUbiViz() {
SmallString<128> P;
int FD;
llvm::sys::fs::createTemporaryFile("llvm_ubi", "", FD, P);
- llvm::errs() << "Writing '" << P.str() << "'.\n";
+ llvm::errs() << "Writing '" << P << "'.\n";
auto Stream = llvm::make_unique<llvm::raw_fd_ostream>(FD, true);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 36565cb..7fced1e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -114,6 +114,7 @@ ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
ClangCheckerRegistry allCheckers(plugins, &diags);
allCheckers.initializeManager(*checkerMgr, checkerOpts);
+ allCheckers.validateCheckerOptions(opts, diags);
checkerMgr->finishedCheckerRegistration();
for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
@@ -125,7 +126,7 @@ ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
}
- return std::move(checkerMgr);
+ return checkerMgr;
}
void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 63bb1e2..ee2c3f5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -69,14 +69,14 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
InputKind IK = IK_CXX; // FIXME
FrontendOpts.Inputs.clear();
- FrontendOpts.Inputs.push_back(FrontendInputFile(fileName, IK));
+ FrontendOpts.Inputs.emplace_back(fileName, IK);
FrontendOpts.DisableFree = true;
Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
// Modules are parsed by a separate CompilerInstance, so this code mimics that
// behavior for models
- CompilerInstance Instance;
+ CompilerInstance Instance(CI.getPCHContainerOperations());
Instance.setInvocation(&*Invocation);
Instance.createDiagnostics(
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
index fd24e32..e23bf8a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/ModelInjector.h
@@ -43,8 +43,8 @@ namespace ento {
class ModelInjector : public CodeInjector {
public:
ModelInjector(CompilerInstance &CI);
- Stmt *getBody(const FunctionDecl *D);
- Stmt *getBody(const ObjCMethodDecl *D);
+ Stmt *getBody(const FunctionDecl *D) override;
+ Stmt *getBody(const ObjCMethodDecl *D) override;
private:
/// \brief Synthesize a body for a declaration
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
index 91c74a4..adae178 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
@@ -54,6 +54,7 @@ const char *const CommonOptionsParser::HelpMessage =
"\tsuffix of a path in the compile command database.\n"
"\n";
+namespace {
class ArgumentsAdjustingCompilations : public CompilationDatabase {
public:
ArgumentsAdjustingCompilations(
@@ -89,6 +90,7 @@ private:
return Commands;
}
};
+} // namespace
CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
cl::OptionCategory &Category,
@@ -112,15 +114,7 @@ CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
cl::desc("Additional argument to prepend to the compiler command line"),
cl::cat(Category));
- // Hide unrelated options.
- StringMap<cl::Option*> Options;
- cl::getRegisteredOptions(Options);
- for (StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end();
- I != E; ++I) {
- if (I->second->Category != &Category && I->first() != "help" &&
- I->first() != "version")
- I->second->setHiddenFlag(cl::ReallyHidden);
- }
+ cl::HideUnrelatedOptions(Category);
Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc,
argv));
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
index 7613988..2272be6 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
@@ -29,9 +29,8 @@
#include "llvm/Support/Path.h"
#include <sstream>
#include <system_error>
-
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
CompilationDatabase::~CompilationDatabase() {}
@@ -109,6 +108,7 @@ CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
+namespace {
// Helper for recursively searching through a chain of actions and collecting
// all inputs, direct and indirect, of compile jobs.
struct CompileJobAnalyzer {
@@ -156,8 +156,8 @@ public:
// recording for our own purposes.
UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info) override {
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
// Arg 1 for this diagnostic is the option that didn't get used.
UnusedInputs.push_back(Info.getArgStdStr(0));
@@ -183,6 +183,7 @@ struct MatchesAny {
private:
ArrayRef<std::string> Arr;
};
+} // namespace
/// \brief Strips any positional args and possible argv[0] from a command-line
/// provided by the user to construct a FixedCompilationDatabase.
@@ -249,14 +250,11 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
CompileJobAnalyzer CompileAnalyzer;
- for (const auto &Job : Jobs) {
- if (Job.getKind() == driver::Job::CommandClass) {
- const driver::Command &Cmd = cast<driver::Command>(Job);
- // Collect only for Assemble jobs. If we do all jobs we get duplicates
- // since Link jobs point to Assemble jobs as inputs.
- if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass)
- CompileAnalyzer.run(&Cmd.getSource());
- }
+ for (const auto &Cmd : Jobs) {
+ // Collect only for Assemble jobs. If we do all jobs we get duplicates
+ // since Link jobs point to Assemble jobs as inputs.
+ if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass)
+ CompileAnalyzer.run(&Cmd.getSource());
}
if (CompileAnalyzer.Inputs.empty()) {
@@ -282,11 +280,9 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
return true;
}
-FixedCompilationDatabase *
-FixedCompilationDatabase::loadFromCommandLine(int &Argc,
- const char **Argv,
- Twine Directory) {
- const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
+FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine(
+ int &Argc, const char *const *Argv, Twine Directory) {
+ const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
if (DoubleDash == Argv + Argc)
return nullptr;
std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
@@ -303,8 +299,7 @@ FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
std::vector<std::string> ToolCommandLine(1, "clang-tool");
ToolCommandLine.insert(ToolCommandLine.end(),
CommandLine.begin(), CommandLine.end());
- CompileCommands.push_back(
- CompileCommand(Directory, std::move(ToolCommandLine)));
+ CompileCommands.emplace_back(Directory, std::move(ToolCommandLine));
}
std::vector<CompileCommand>
@@ -324,6 +319,9 @@ FixedCompilationDatabase::getAllCompileCommands() const {
return std::vector<CompileCommand>();
}
+namespace clang {
+namespace tooling {
+
// This anchor is used to force the linker to link in the generated object file
// and thus register the JSONCompilationDatabasePlugin.
extern volatile int JSONAnchorSource;
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
index 525f7df..6d37a49 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
@@ -43,8 +43,9 @@ Replacement::Replacement(const SourceManager &Sources, SourceLocation Start,
Replacement::Replacement(const SourceManager &Sources,
const CharSourceRange &Range,
- StringRef ReplacementText) {
- setFromSourceRange(Sources, Range, ReplacementText);
+ StringRef ReplacementText,
+ const LangOptions &LangOpts) {
+ setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
}
bool Replacement::isApplicable() const {
@@ -77,18 +78,23 @@ bool Replacement::apply(Rewriter &Rewrite) const {
}
std::string Replacement::toString() const {
- std::string result;
- llvm::raw_string_ostream stream(result);
- stream << FilePath << ": " << ReplacementRange.getOffset() << ":+"
+ std::string Result;
+ llvm::raw_string_ostream Stream(Result);
+ Stream << FilePath << ": " << ReplacementRange.getOffset() << ":+"
<< ReplacementRange.getLength() << ":\"" << ReplacementText << "\"";
- return result;
+ return Stream.str();
}
bool operator<(const Replacement &LHS, const Replacement &RHS) {
if (LHS.getOffset() != RHS.getOffset())
return LHS.getOffset() < RHS.getOffset();
+
+ // Apply longer replacements first, specifically so that deletions are
+ // executed before insertions. It is (hopefully) never the intention to
+ // delete parts of newly inserted code.
if (LHS.getLength() != RHS.getLength())
- return LHS.getLength() < RHS.getLength();
+ return LHS.getLength() > RHS.getLength();
+
if (LHS.getFilePath() != RHS.getFilePath())
return LHS.getFilePath() < RHS.getFilePath();
return LHS.getReplacementText() < RHS.getReplacementText();
@@ -124,23 +130,25 @@ void Replacement::setFromSourceLocation(const SourceManager &Sources,
// to handle ranges for refactoring in general first - there is no obvious
// good way how to integrate this into the Lexer yet.
static int getRangeSize(const SourceManager &Sources,
- const CharSourceRange &Range) {
+ const CharSourceRange &Range,
+ const LangOptions &LangOpts) {
SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin());
SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd());
std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin);
std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd);
if (Start.first != End.first) return -1;
if (Range.isTokenRange())
- End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources,
- LangOptions());
+ End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources, LangOpts);
return End.second - Start.second;
}
void Replacement::setFromSourceRange(const SourceManager &Sources,
const CharSourceRange &Range,
- StringRef ReplacementText) {
+ StringRef ReplacementText,
+ const LangOptions &LangOpts) {
setFromSourceLocation(Sources, Sources.getSpellingLoc(Range.getBegin()),
- getRangeSize(Sources, Range), ReplacementText);
+ getRangeSize(Sources, Range, LangOpts),
+ ReplacementText);
}
unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
diff --git a/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp b/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
index dc9999e..86ed036 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/FileMatchTrie.cpp
@@ -17,18 +17,20 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <sstream>
+using namespace clang;
+using namespace tooling;
-namespace clang {
-namespace tooling {
-
+namespace {
/// \brief Default \c PathComparator using \c llvm::sys::fs::equivalent().
struct DefaultPathComparator : public PathComparator {
- virtual ~DefaultPathComparator() {}
bool equivalent(StringRef FileA, StringRef FileB) const override {
return FileA == FileB || llvm::sys::fs::equivalent(FileA, FileB);
}
};
+}
+namespace clang {
+namespace tooling {
/// \brief A node of the \c FileMatchTrie.
///
/// Each node has storage for up to one path and a map mapping a path segment to
@@ -156,6 +158,8 @@ private:
// The children of this node stored in a map based on the next path segment.
llvm::StringMap<FileMatchTrieNode> Children;
};
+} // end namespace tooling
+} // end namespace clang
FileMatchTrie::FileMatchTrie()
: Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
@@ -183,6 +187,3 @@ StringRef FileMatchTrie::findEquivalent(StringRef FileName,
Error << "Path is ambiguous";
return Result;
}
-
-} // end namespace tooling
-} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
index 3b5f7e2..454a2ff 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -176,7 +176,7 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
std::string Error;
llvm::raw_string_ostream ES(Error);
- StringRef Match = MatchTrie.findEquivalent(NativeFilePath.str(), ES);
+ StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES);
if (Match.empty())
return std::vector<CompileCommand>();
llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
@@ -220,10 +220,10 @@ void JSONCompilationDatabase::getCommands(
for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
SmallString<8> DirectoryStorage;
SmallString<1024> CommandStorage;
- Commands.push_back(CompileCommand(
- // FIXME: Escape correctly:
- CommandsRef[I].first->getValue(DirectoryStorage),
- unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
+ Commands.emplace_back(
+ // FIXME: Escape correctly:
+ CommandsRef[I].first->getValue(DirectoryStorage),
+ unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)));
}
}
@@ -307,13 +307,13 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
SmallString<128> AbsolutePath(
Directory->getValue(DirectoryStorage));
llvm::sys::path::append(AbsolutePath, FileName);
- llvm::sys::path::native(AbsolutePath.str(), NativeFilePath);
+ llvm::sys::path::native(AbsolutePath, NativeFilePath);
} else {
llvm::sys::path::native(FileName, NativeFilePath);
}
IndexByFile[NativeFilePath].push_back(
CompileCommandRef(Directory, Command));
- MatchTrie.insert(NativeFilePath.str());
+ MatchTrie.insert(NativeFilePath);
}
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring.cpp
index c817306..d32452f 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring.cpp
@@ -25,9 +25,10 @@
namespace clang {
namespace tooling {
-RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations,
- ArrayRef<std::string> SourcePaths)
- : ClangTool(Compilations, SourcePaths) {}
+RefactoringTool::RefactoringTool(
+ const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : ClangTool(Compilations, SourcePaths, PCHContainerOps) {}
Replacements &RefactoringTool::getReplacements() { return Replace; }
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
index 60371fb..f9cb7c6 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
@@ -90,7 +90,7 @@ static const llvm::opt::ArgStringList *getCC1Arguments(
}
/// \brief Returns a clang build invocation initialized from the CC1 flags.
-static clang::CompilerInvocation *newInvocation(
+clang::CompilerInvocation *newInvocation(
clang::DiagnosticsEngine *Diagnostics,
const llvm::opt::ArgStringList &CC1Args) {
assert(!CC1Args.empty() && "Must at least contain the program name!");
@@ -105,9 +105,10 @@ static clang::CompilerInvocation *newInvocation(
}
bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
- const Twine &FileName) {
- return runToolOnCodeWithArgs(
- ToolAction, Code, std::vector<std::string>(), FileName);
+ const Twine &FileName,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
+ return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(),
+ FileName, PCHContainerOps);
}
static std::vector<std::string>
@@ -121,17 +122,18 @@ getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs,
return Args;
}
-bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
- const std::vector<std::string> &Args,
- const Twine &FileName,
- const FileContentMappings &VirtualMappedFiles) {
+bool runToolOnCodeWithArgs(
+ clang::FrontendAction *ToolAction, const Twine &Code,
+ const std::vector<std::string> &Args, const Twine &FileName,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ const FileContentMappings &VirtualMappedFiles) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions()));
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef),
- ToolAction, Files.get());
+ ToolAction, Files.get(), PCHContainerOps);
SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
@@ -173,21 +175,18 @@ public:
}
-ToolInvocation::ToolInvocation(std::vector<std::string> CommandLine,
- ToolAction *Action, FileManager *Files)
- : CommandLine(std::move(CommandLine)),
- Action(Action),
- OwnsAction(false),
- Files(Files),
- DiagConsumer(nullptr) {}
+ToolInvocation::ToolInvocation(
+ std::vector<std::string> CommandLine, ToolAction *Action,
+ FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false),
+ Files(Files), PCHContainerOps(PCHContainerOps), DiagConsumer(nullptr) {}
-ToolInvocation::ToolInvocation(std::vector<std::string> CommandLine,
- FrontendAction *FAction, FileManager *Files)
+ToolInvocation::ToolInvocation(
+ std::vector<std::string> CommandLine, FrontendAction *FAction,
+ FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)),
- Action(new SingleFrontendActionFactory(FAction)),
- OwnsAction(true),
- Files(Files),
- DiagConsumer(nullptr) {}
+ Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),
+ Files(Files), PCHContainerOps(PCHContainerOps), DiagConsumer(nullptr) {}
ToolInvocation::~ToolInvocation() {
if (OwnsAction)
@@ -232,13 +231,14 @@ bool ToolInvocation::run() {
Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
Input.release());
}
- return runInvocation(BinaryName, Compilation.get(), Invocation.release());
+ return runInvocation(BinaryName, Compilation.get(), Invocation.release(),
+ PCHContainerOps);
}
bool ToolInvocation::runInvocation(
- const char *BinaryName,
- clang::driver::Compilation *Compilation,
- clang::CompilerInvocation *Invocation) {
+ const char *BinaryName, clang::driver::Compilation *Compilation,
+ clang::CompilerInvocation *Invocation,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
// Show the invocation, with -v.
if (Invocation->getHeaderSearchOpts().Verbose) {
llvm::errs() << "clang Invocation:\n";
@@ -246,14 +246,16 @@ bool ToolInvocation::runInvocation(
llvm::errs() << "\n";
}
- return Action->runInvocation(Invocation, Files, DiagConsumer);
+ return Action->runInvocation(Invocation, Files, PCHContainerOps,
+ DiagConsumer);
}
-bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation,
- FileManager *Files,
- DiagnosticConsumer *DiagConsumer) {
+bool FrontendActionFactory::runInvocation(
+ CompilerInvocation *Invocation, FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagConsumer) {
// Create a compiler instance to handle the actual work.
- clang::CompilerInstance Compiler;
+ clang::CompilerInstance Compiler(PCHContainerOps);
Compiler.setInvocation(Invocation);
Compiler.setFileManager(Files);
@@ -276,8 +278,10 @@ bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation,
}
ClangTool::ClangTool(const CompilationDatabase &Compilations,
- ArrayRef<std::string> SourcePaths)
+ ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: Compilations(Compilations), SourcePaths(SourcePaths),
+ PCHContainerOps(PCHContainerOps),
Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) {
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
@@ -357,7 +361,8 @@ int ClangTool::run(ToolAction *Action) {
// FIXME: We need a callback mechanism for the tool writer to output a
// customized message for each file.
DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
- ToolInvocation Invocation(std::move(CommandLine), Action, Files.get());
+ ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
+ PCHContainerOps);
Invocation.setDiagnosticConsumer(DiagConsumer);
for (const auto &MappedFile : MappedFileContents)
Invocation.mapVirtualFile(MappedFile.first, MappedFile.second);
@@ -385,12 +390,14 @@ public:
ASTBuilderAction(std::vector<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
bool runInvocation(CompilerInvocation *Invocation, FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
// FIXME: This should use the provided FileManager.
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
- Invocation, CompilerInstance::createDiagnostics(
- &Invocation->getDiagnosticOpts(), DiagConsumer,
- /*ShouldOwnClient=*/false));
+ Invocation, PCHContainerOps,
+ CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
+ DiagConsumer,
+ /*ShouldOwnClient=*/false));
if (!AST)
return false;
@@ -406,22 +413,24 @@ int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
return run(&Action);
}
-std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code,
- const Twine &FileName) {
- return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName);
+std::unique_ptr<ASTUnit>
+buildASTFromCode(const Twine &Code, const Twine &FileName,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
+ return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
+ PCHContainerOps);
}
-std::unique_ptr<ASTUnit>
-buildASTFromCodeWithArgs(const Twine &Code,
- const std::vector<std::string> &Args,
- const Twine &FileName) {
+std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
+ const Twine &Code, const std::vector<std::string> &Args,
+ const Twine &FileName,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action,
- nullptr);
+ nullptr, PCHContainerOps);
SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
OpenPOWER on IntegriCloud